Report on coverage and gaps in the response to the Venezuela Migrant and Economic Crisis, 2019

This coverage and gaps analysis is intended to analyse and provide recommendations on how best to reach populations in need not currently covered by humanitarian action. This is an automated reported intended to serve as a template for coverage and gaps analyses. Data originates from the Education, Health, Nutrition, Protection and WASH Clusters from 2019. Partner data has been anonymised.

Coverage and gaps analyses are key documents, but are also rarely taken into account during strategic planning or referenced in revisions of major guiding documents, such as HRPs. They are not mentioned in OCHA’s Humanitarian Response Planning guidance. And it remains an industry-wide challenge to respond and adapt to gaps in coverage and reallocate resources accordingly.

Reading in the data and doing the initial cleaning

Unlike the document of 5W reporting and cleaning, we will not be exploring the cleaning process. But you can unhide any of the code chunks to see the details by clicking the “Code” button.

# function to remove accents 
rm_accent <- function(colns){
  colns <- stri_trans_general(colns, "Latin-ASCII")
}

# reading and cleaning -- you really should break it into parts
ven1 <- read_csv("consolidation 191209 1635.csv") %>% 
  clean_names() %>% 
  # removing unused columns
  select(-c(codigodeestablecimientoocentro, loc_id, hrp_sitre_p_indicator, 
            tipoderespuesta, comentarios, coordeadas_gps_x, coordeadas_gps_y,
            fechade_inicio, fecha_previstade_finalizacion)) %>% 
  # renaming unwieldy columns 
  rename(ubicacion          = comunidadonombredelestablecimiento_centro, 
         sector             = sector_areade_responsabiliad,
         beneficiarios_meta = beneficiarios_meta_numerodepersonas,
         estatus            = estatusdeprogramacion) %>% 
      # mutating the date to the right format
  mutate(month = as.factor(recode(month,
                        `4` = "30/04/2019",
                        `5` = "31/05/2019",
                        `6` = "30/06/2019",
                        `7` = "31/07/2019",
                        `8` = "31/08/2019",
                        `9` = "30/09/2019",
                        `10` = "31/10/2019"))) %>% 
  mutate(month = as.Date(month %>% strptime(., format = "%d/%m/%Y"))) %>% 
  mutate(org_lider = coalesce(org_lider, org_implementadora)) %>% 
  # correcting sector names
  mutate(sector = str_replace_all(sector, c(
    "Agua_saneamiento_higiene"            = "WASH",
    "educacion"                           = "Educacion",
    "Nutricion"                           = "Nutricion",
    "protección_Niños_Niñas_Adolescentes" = "Proteccion_NNA",
    "Protección_Niños_Niñas_Adolescentes" = "Proteccion_NNA",
    "Protección_Violencia_Género"         = "Proteccion_GBV"))) %>% 
  # renaming beneficiary disaggregation columns 
  rename(f_0_18 = f_18,
         m_0_18 = m_18,
         f_18plus = f_18_2,
         m_18plus = m_18_2) %>% 
  mutate(estado    = rm_accent(str_to_upper(estado)), 
         municipio = rm_accent(str_to_upper(municipio)),
         parroquia = rm_accent(str_to_upper(parroquia)),
         ubicacion = rm_accent(str_to_upper(ubicacion)),
         actividad = rm_accent(str_to_upper(actividad)),
         categoria = rm_accent(str_to_upper(categoriadeactividad))) %>% 
  # recoding the estatus column 
  mutate(estatus = str_replace_all(estatus, 
                  c("En ejecucion" = "ejecucion", 
                    "en ejecución" = "ejecucion", 
                    "en Ejecución" = "ejecucion",
                    "En ejecución" = "ejecucion",
                    "En Ejecución" = "ejecucion",
                    "Enejecución"  = "ejecucion",
                    "43741"        = "ejecucion",
                    "finalizada" = "finalizada",
                    "Finalizada" = "finalizada",
                    "Planeada" = "planeada",
                    "planeada con financiamiento" = "planeada",
                    "planeada sin financiamiento" = "planeada"))) %>% 
  replace_na(list(estatus = "ejecucion")) %>% 
  # removing all planned activities 
  filter(estatus != "planeada") %>% 
  filter(str_detect(pcode3, "^VE")) %>% # decide if you want to do this here or later
  select(-c(23:92))
# I'm kinda doubting the use of u_ben, ya I think take it out? since you're only using it once
# Am I just making these out of habit? I could cut them and make them inside the 
# code chunk for parr, but maybe I can find some justification for their existence, 
# maybe the disaggregations? 

# Vaccination activities filtered out
u_ben <- ven1 %>% 
  pivot_longer(f_0_18:m_18plus, names_to = "desagregacion", values_to = "beneficiarios") %>% 
  filter(categoriadeactividad != "Vacunacion") %>% 
  filter(beneficiarios != 0) %>% 
  group_by(ubicacion, desagregacion) %>% 
  slice(which.max(beneficiarios)) %>% 
  ungroup()

act_ben <- ven1 %>% 
  pivot_longer(f_0_18:m_18plus, names_to = "desagregacion", values_to = "beneficiarios") %>% 
  filter(beneficiarios != 0) %>% 
  group_by(ubicacion, desagregacion, actividad) %>% 
  slice(which.max(beneficiarios)) %>% 
  ungroup()

# rbind(sum(u_ben$beneficiarios), 
#       sum(act_ben$beneficiarios), 
#       sum(u_ben$beneficiarios) - sum(act_ben$beneficiarios))
# I think this is a gigantic chunk -- cannot decide if I would rather have less things in the 
# environment or if I want more readable chunks. The benefit here I guess is that if I want to change something, I just have to come to this chunk

parr <- u_ben %>% 
  group_by(pcode3) %>% 
  summarise(beneficiarios = sum(beneficiarios)) %>% 
  ungroup() %>% 
  left_join(act_ben %>% 
             filter(categoria != "Vacunacion") %>%
             group_by(ubicacion, desagregacion, sector) %>% 
                slice(which.max(beneficiarios)) %>% 
                ungroup() %>% 
                pivot_wider(names_from = sector, values_from = beneficiarios) %>% 
                group_by(pcode3) %>% 
                # getting sector totals per pcode3
                summarise(educacion_ben = sum(Educacion, na.rm = TRUE),
                          nutricion_ben = sum(Nutricion, na.rm = TRUE),
                          proteccionGBV_ben = sum(Proteccion_GBV, na.rm = TRUE),
                          proteccionGeneral_ben = sum(Proteccion_General, na.rm = TRUE),
                          proteccionNNA_ben = sum(Proteccion_NNA, na.rm = TRUE),
                          salud_ben = sum(Salud, na.rm = TRUE),
                          seguridad_alimentaria_ben = sum(Seguridad_Alimentaria, na.rm = TRUE),
                          wash_ben = sum(WASH, na.rm = TRUE),
                          org_count = n_distinct(org_implementadora)) %>% 
             ungroup()) %>% 
  filter(str_detect(pcode3, "^VE")) %>% 
  # right_join to the census data
  right_join(read_excel("census data 20191122.xlsx", sheet = "data") %>% 
        clean_names() %>% 
        # selecting variables and renaming them with select
        select(estado, pcode1, municipio, pcode2, parroquia, pcode3, 
               fo = field_office,
               poblacion_2019 = x_2019_poblacion_parroquial_total,
               hogares_2011 = numero_de_hogares, 
               ham_2019_ambitos_ge, 
               percent_pobre = ham_2019_xx_pobreza_env_por_parroquia, 
               pob_pobre = ham_2019_xx_poblacion_pobre_por_parroquia, 
               poblacion_total_2011,
               poblacion_infantil_menor_de_12_anos, poblacion_adolescentes_de_12_a_17_anos,
               poblacion_de_18_anos_y_mas, 
               percent_urbana = poblacion_urbana_percent, 
               area_km2, 
               densidad_ppl_km2 = densidad_poblacional_ppl_km2,
               matricula_2017_educacion_inicial, matricula_2017_educacion_primaria, 
               matricula_2017_educacion_media, razon_de_dependencia_total,
               razon_de_dependencia_de_menores_de_15_anos, 
               percent_sin_agua_segura = x_abast_agua2_percent_sin_agua_segura,
               percent_sin_saneamiento_mejorado =
                 x_saneamiento_percent_sin_saneamiento_mejorado,
               percent_analfabeto = percent_poblacion_10_anos_y_mas_analfabeta,
               promedio_de_personas_por_vivienda,
               percent_hogares_jefatura_femenina = percent_de_hogares_con_jefatura_femenina,
               percent_sin_servicio_electrico =
                 servicio_electrico_percent_no_tiene_servicio_electrico,
               ham_2019_x_violencia_envelope, ham_2019_x_mortalidad_y_salud_envelope, 
               ham_2019_x_pobreza_envelope, promedio_de_edad) %>% 
        mutate(estado     = rm_accent(str_to_upper(estado)), # just to make sure 
               municipio  = rm_accent(str_to_upper(municipio)),
               parroquia  = rm_accent(str_to_upper(parroquia))) %>% 
        # creating new disaggregation variables 
        mutate(pob_menor_de_18 = (poblacion_infantil_menor_de_12_anos +
                                 poblacion_adolescentes_de_12_a_17_anos) /poblacion_total_2011 *
                                 poblacion_2019, 
               pob_18_y_mas    = poblacion_de_18_anos_y_mas / poblacion_total_2011 * poblacion_2019, 
               hogares_2019    = hogares_2011 * poblacion_2019 / poblacion_total_2011, 
               matricula_total = matricula_2017_educacion_inicial + 
                                 matricula_2017_educacion_primaria + 
                                 matricula_2017_educacion_media) %>% 
        # dividing columns by 100 to clean then and put them between 0 and 1
        mutate_at(vars(percent_analfabeto, percent_sin_servicio_electrico, 
                       percent_sin_agua_segura,
                       percent_sin_saneamiento_mejorado,
                       percent_hogares_jefatura_femenina, percent_urbana,
                       razon_de_dependencia_total), ~(. / 100)) %>% 
        # mutating new columns with populations
        mutate(pob_analfabeto               = percent_analfabeto * poblacion_2019,
               pob_sin_agua_segura          = percent_sin_agua_segura * poblacion_2019, 
               pob_sin_servicio_electrico   = percent_sin_servicio_electrico * poblacion_2019,
               pob_sin_saneamiento_mejorado = percent_sin_saneamiento_mejorado * poblacion_2019,
               pob_urbana                   = percent_urbana * poblacion_2019) %>% 
        select(-c(matricula_2017_educacion_inicial, matricula_2017_educacion_primaria, 
               matricula_2017_educacion_media, poblacion_total_2011, hogares_2011,
               poblacion_infantil_menor_de_12_anos, poblacion_adolescentes_de_12_a_17_anos, 
               poblacion_de_18_anos_y_mas)),
             by = "pcode3") %>% 
  # mutating new variables and making sure NAs become 0s 
  mutate(beneficiarios          = ifelse(is.na(beneficiarios), 0, beneficiarios),
         org_count              = ifelse(is.na(org_count), 0, org_count),
         educacion_ben             = ifelse(is.na(educacion_ben), 0, educacion_ben),
         nutricion_ben             = ifelse(is.na(nutricion_ben), 0, nutricion_ben),
         proteccionGBV_ben         = ifelse(is.na(proteccionGBV_ben), 0, proteccionGBV_ben),
         proteccionGeneral_ben     = ifelse(is.na(proteccionGeneral_ben), 0, proteccionGeneral_ben),
         proteccionNNA_ben         = ifelse(is.na(proteccionNNA_ben), 0, proteccionNNA_ben),
         salud_ben                 = ifelse(is.na(salud_ben), 0, salud_ben),
         seguridad_alimentaria_ben = ifelse(is.na(seguridad_alimentaria_ben), 0, seguridad_alimentaria_ben),
         wash_ben                  = ifelse(is.na(wash_ben), 0, wash_ben),
         not_covered_pobre      = pob_pobre - beneficiarios,
         coverage_percent       = beneficiarios / poblacion_2019,
         coverage_pobre_percent = beneficiarios / pob_pobre,
         percent_total_ben      = beneficiarios / sum(beneficiarios),
         org_present            = ifelse(beneficiarios > 0, TRUE, FALSE),
         pob_pobre_score     = rescale(pob_pobre, to = c(0,1)), 
         percent_pobre_score = rescale(percent_pobre, to = c(0,1)), 
         poverty_score       = (pob_pobre_score + percent_pobre_score) / 2)

# taking a subset of parr to only get parrishes where the number of beneficiaries does not exceed the number of poor persons
parr0 <- parr %>% 
  filter(not_covered_pobre >= 1) %>% 
  mutate(gap_score = (rescale(not_covered_pobre, to = c(0,1)) + percent_pobre_score) / 2)

Summary of coverage and gaps

As a preliminary analysis, all 1109 parrishes have been split into three groups – over, where the number of unique beneficiaries reached exceeds the number of poor persons in that parrish; under, where the coverage is less than the number of poor persons; and not reached, where no activities have occurred. However, it should be noted that a total of 2875136 poor persons reside in the 531 parrishes that have not been reached, this is only 26% of the 11172989 poor persons not covered by response activities. This indicates that 1) there is much room to expand in the parrishes where we are already present and 2) sparely populated, remote and, consequently, poorer parrishes have, so far, been left out of the response.

parr %>% 
  mutate(coverage_type = case_when(not_covered_pobre <= 0 ~ "over",
                                   not_covered_pobre > 0 & beneficiarios >= 1 ~ "under", 
                                   beneficiarios == 0 ~ "not_reached")) %>% 
  group_by(coverage_type) %>% 
  summarise(parroquias = n(),
            beneficiarios = sum(beneficiarios),
            not_covered_pobre = sum(not_covered_pobre), 
            avg_org_count = mean(org_count),
            percent_pobre = (sum(pob_pobre)) / (sum(poblacion_2019)),
            percent_urbana = (sum(pob_urbana)) / (sum(poblacion_2019)),
            percent_sin_agua_segura = (sum(pob_sin_agua_segura)) / (sum(poblacion_2019)),
            percent_sin_saneamiento_mejorado = (sum(pob_sin_saneamiento_mejorado)) /
              (sum(poblacion_2019))) %>% 
  gather(key = variable, value = value, 2:ncol(.)) %>% 
  spread_(key = names(.)[1], value = 'value') %>% 
  relocate(not_reached, .after = under) %>% 
  pander(big.mark = ",")
variable over under not_reached
avg_org_count 7.727 2.668 0
beneficiarios 658,812 655,278 0
not_covered_pobre -463,891 8,761,744 2,875,136
parroquias 11 567 531
percent_pobre 0.2029 0.3744 0.4568
percent_sin_agua_segura 0.02017 0.1322 0.2256
percent_sin_saneamiento_mejorado 0.01024 0.07014 0.1757
percent_urbana 0.9948 0.9298 0.69

We note that the 11 parrishes in the over category are much less poor and much more urban despite having 50% of all beneficiaries. These parrishes are shown in the table below.

Top parrishes in terms of coverage

parr %>% 
  mutate(coverage_type = case_when(not_covered_pobre <= 0 ~ "over",
                                   not_covered_pobre > 0 & beneficiarios >= 1 ~ "under", 
                                   beneficiarios == 0 ~ "not_reached")) %>%  
  filter(coverage_type == "over") %>% 
  select(estado, municipio, estado, parroquia, beneficiarios, pob_pobre) %>%
  mutate(coverage_poor = beneficiarios / pob_pobre * 100) %>% 
  arrange(desc(beneficiarios)) %>% 
  pander(big.mark = ",")
estado municipio parroquia beneficiarios pob_pobre coverage_poor
DISTRITO CAPITAL LIBERTADOR ALTAGRACIA 321,597 6,244 5,151
MIRANDA SUCRE PETARE 178,814 82,058 217.9
BOLIVAR CARONI ONCE DE ABRIL 69,332 54,118 128.1
BOLIVAR HERES CATEDRAL 32,177 14,336 224.4
BOLIVAR HERES VISTA HERMOSA 18,477 13,919 132.7
MIRANDA CHACAO CHACAO 13,780 5,481 251.4
TACHIRA ANDRES BELLO CAPITAL CORDERO 8,596 7,766 110.7
MIRANDA SUCRE LEONCIO MARTINEZ 6,834 4,792 142.6
CARABOBO VALENCIA URBANA CANDELARIA 5,043 4,589 109.9
TACHIRA BOLIVAR GENERAL JUAN VICENTE GOMEZ 2,253 362.1 622.3
DELTA AMACURO TUCUPITA SAN JOSE 1,909 1,256 152

These 11 parrishes will largely be excluded in the analysis in the remainder of this report as it is clear that no further resources should be allocated to them.

Though it should be mentioned that it is likely that partners have reported activities which occurred in other parts of the capital in Altagracia, as the total number of benefificaries reached in the whole of Distrito Capital is only 415301. This analysis will be corrected if updated information is received.

Geographical analysis of Gaps

Barplot of coverage and gaps by state

mouse over plot for more details

# ref for printng state_ord. I'm really not sure how to extract all the variables as a list
# parr0 %>% 
#   group_by(estado) %>% 
#   summarise(not_covered_pobre = sum(not_covered_pobre)) %>% 
#   arrange(desc(not_covered_pobre)) %>% 
#   select(estado) %>% as.list(as.data.frame(t(.)))

state_ord <- c("ZULIA", "LARA", "CARABOBO", "MIRANDA", "ANZOATEGUI", "ARAGUA", "BOLIVAR",
               "PORTUGUESA", "SUCRE", "GUARICO", "FALCON", "MONAGAS", "BARINAS", "MERIDA",
               "TACHIRA", "TRUJILLO", "YARACUY", "APURE", "DISTRITO CAPITAL", "NUEVA ESPARTA",
               "COJEDES", "VARGAS", "DELTA AMACURO", "AMAZONAS")
  
stack_text <- parr0 %>% 
  group_by(estado) %>% 
  summarise(beneficiarios = sum(beneficiarios),
            total = sum(pob_pobre)) %>% 
  mutate(percent_reached = round(beneficiarios / total * 100, digits = 2)) %>% 
  arrange(desc(total)) 

state_stack <- parr0 %>% 
  select(estado, beneficiarios, not_covered_pobre) %>% 
  group_by(estado) %>%
  summarise(beneficiarios = sum(beneficiarios), 
            not_covered_pobre = sum(not_covered_pobre)) %>% 
  pivot_longer(c(beneficiarios,not_covered_pobre),
               names_to = "pob_type", values_to = "total") %>% 
  
  ggplot(aes(x = estado, y = total)) +
  geom_col(aes(fill = pob_type)) +
  scale_y_continuous(label = comma) +
  scale_x_discrete(limits = state_ord) +
  geom_text(data = stack_text, aes(y = 20000,
                                   label = percent_reached), size = 2) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 5),
        axis.text.y = element_text(size = 5),
        axis.title.y = element_text(size = 8)) +
  xlab("") + ylab("Poor persons") + labs(fill = "")

ggplotly(state_stack) %>% 
  layout(legend = list(font = list(size = 6))) %>% 
  config(displayModeBar = FALSE)

The states with the highest percentages (listed at the bottom of each bar) are Distrito Capital, Tachira, Bolivar, Delta Amacuro, Miranda and Zulia. Carabobo has the lowest percentage of its poor population covered. On average, after the exclusion of the top 11 parrishes, 10.5% of poor persons have been reached.

Let us now move down to a lower level of granularity as state-level analysis is stil quite superficial:

Scatterplot of gaps by parrish

parrplot <- parr0 %>% 
  mutate_at(vars(pob_pobre, not_covered_pobre, org_count), ~(round(.))) %>% 
  mutate(percent_pobre = round(percent_pobre, digits = 2))%>% 
  ggplot(aes(x = not_covered_pobre, y = percent_pobre, 
             colour = org_count, 
             text = paste0(parroquia, ", ", estado))) +
  geom_point(aes(size = not_covered_pobre), alpha = 0.75) +
  scale_colour_gradientn(
    colours = c("cornflowerblue", "tomato", "firebrick")) +
  scale_x_continuous(trans = "log10", labels = comma) + 
  scale_size_continuous(range = c(0.3, 5)) +
  xlab("Not covered poor") + ylab("Poverty incidence") +
  labs(colour = "Number of \norganisations") +
  theme(legend.title = element_text(size = 7),
        legend.text = element_text(size = 7))

ggplotly(parrplot, tooltip = c("y", "x", "size", "text", "colour")) %>% 
           layout(showlegend = TRUE, legend = list(font = list(size = 7))) %>% 
           config(displayModeBar = FALSE)

x-axis: number of poor persons; y-axis: poverty incidence; size: number of poor persons not covered; colour: number of organisations present mouse over for details

However, from the scatterplot above – where each point is a parrish and the size shows the number of poor persons not covered (not covered) – we see that there is great variation in the number of those not covered as well as how concentrated they are in a given parrish (poverty incidence); both these factors weigh heavily in programming strategies as well as in the ease of beneficiary selection.

But we can, at least, observe that the parrishes with the greatest numbers of not covered (found at poor persons: 10,000-100,000; poverty incidence: 0.25-0.50) have a much higher than average number of organisations present. This means that operational barriers are much lower in accessing these populations than the parrishes in light blue found in the middle of the plot.

For a more detailed plot, with state filters, please visit this link:

Scatterplot of coverage and gaps in multi-sector programming

sector_plot <- parr0 %>% 
  mutate(proteccion_ben = rowSums(.[5:7])) %>% 
  select(-c(proteccionGBV_ben, proteccionGeneral_ben, proteccionNNA_ben, percent_total_ben, seguridad_alimentaria_ben)) %>% 
  mutate(sector_count = rowSums(select(., ends_with("_ben"))!=0)) %>% 
  mutate_at(vars(pob_pobre, not_covered_pobre, org_count), ~(round(.))) %>% 
  mutate(percent_pobre = round(percent_pobre, digits = 2))%>% 
  ggplot(aes(x = not_covered_pobre, y = percent_pobre, 
             text = paste0(parroquia, ", ", estado), 
             size = not_covered_pobre)) +
  geom_point(aes(colour = sector_count), alpha = 0.75) +
  scale_x_continuous(trans = "log10", labels = comma) + 
  scale_size_continuous(range = c(0.3, 5)) +
  scale_colour_gradientn(
    colours = c("cornflowerblue", "mediumpurple", "firebrick")) +
  xlab("Not covered poor") + ylab("Poverty incidence") +
  labs(colour = "Number of \nsectors", size = "") +
  theme(legend.title = element_text(size = 7),
        legend.text = element_text(size = 7))

ggplotly(sector_plot, tooltip = c("y", "x", "text", "colour")) %>% 
  layout(showlegend = TRUE, legend = list(font = list(size = 7))) %>%
  config(displayModeBar = FALSE)

x-axis: number of poor persons; y-axis: poverty incidence; size: number of poor persons not covered; colour: number of sectors mouse over for details

Reference Table

Move this reference table to the back

parr0 %>% 
  mutate(proteccion_ben = rowSums(.[5:7])) %>% 
  select(-c(proteccionGBV_ben, proteccionGeneral_ben, proteccionNNA_ben, percent_total_ben, seguridad_alimentaria_ben)) %>% 
  mutate(sector_count = rowSums(select(., ends_with("_ben"))!=0)) %>% 
  mutate_at(vars(pob_pobre, not_covered_pobre, org_count), ~(round(.))) %>% 
  mutate(percent_pobre = round(percent_pobre, digits = 2)) %>% 
  select(estado, municipio, parroquia, pcode3, org_count, sector_count, 
         percent_pobre, percent_urbana, not_covered_pobre,
         beneficiarios, educacion_ben, nutricion_ben, proteccion_ben, salud_ben, wash_ben) %>% 
  arrange(desc(not_covered_pobre)) %>% 
  datatable(filter = "top", options = list(pageLength = 10, scrollX = TRUE)) %>% 
  DT::formatStyle(columns = colnames(.), fontsize = "12pt")

Decision trees

Three trees have been built to split parroquias up into targetting groups based on their characteristics. The variables selected largely originate from the census dataset, with some having been upgraded by the 2019 Municipal Prioritisation Tool, which was a Principal Components Analysis of key variables related to poverty, health and mortality and violence and insecurity.

Parrishes were split into groups based on their various characteristics; the three trees developed were used to split parrishes into groups based on:

  1. The number of poor persons not covered by humanitarian partners;
  2. Whether or not humanitarian partners were present – this was to understand the biases and dispositions partners had in selecting where to work; and
  3. The poverty score, which is just a rescaled average of the number of poor persons and the poverty incidence of each parrish.

The specific variables and formulae used for each of the trees can be seen by unhiding the source code in the chunk below.

# we may fit new trees in the future as more data comes in and test existing ones with new data. They aren't really meant to be predictive and more to organise a response -- we're not really using them to train a model. Tree2, in particular is very backward-looking, though it would be interesting to see how well it holds up over time. Hopefully it's not very predictive. 

set.seed(3000)


# number of not covered poor persons 
tree1 <- parr0 %>%
  rpart(not_covered_pobre ~ estado + percent_pobre + percent_urbana + 
        densidad_ppl_km2 + razon_de_dependencia_de_menores_de_15_anos + 
        razon_de_dependencia_total +  
        percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
        percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina, 
        promedio_de_personas_por_vivienda, data = ., cp = 0.038)

# interested again -- just to show the decision tree of how partners seem to have chosen locations. # using full parr dataset for the tree
tree2 <- parr %>% 
  rpart(org_present ~ percent_pobre + percent_urbana + densidad_ppl_km2 + 
        razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +  
        percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
        percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina, 
        promedio_de_personas_por_vivienda, data = ., minbucket = 100)

# tree based on poverty_score
tree3 <- parr0 %>%
  rpart(poverty_score ~ estado + percent_urbana + densidad_ppl_km2 +
        razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +  
        percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
        percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina,
        promedio_de_personas_por_vivienda, data = ., cp = 0.044)

# tree based on gap score -- let's not use this as tree3 is more stable and will not change based on new 5W data 
tree4 <- parr0 %>%
  rpart(gap_score ~ estado + percent_urbana + densidad_ppl_km2 +
        razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +  
        percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
        percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina, 
        promedio_de_personas_por_vivienda, data = ., cp = 0.045)

# adding tree1 and tree3 rules to the dataset 
parr0 <- parr0 %>% 
  mutate(rule1 = row.names(tree1$frame)[tree1$where]) %>%
      left_join(rpart.rules.table(tree1) %>% 
      filter(Leaf == TRUE) %>% 
      rename(rule1 = Rule) %>% 
      group_by(rule1) %>% 
      summarise(subrules1 = paste(Subrule, collapse = ",")))  %>% 
  mutate(rule3 = row.names(tree3$frame)[tree3$where]) %>%
      left_join(rpart.rules.table(tree3) %>% 
      filter(Leaf == TRUE) %>% 
      rename(rule3 = Rule) %>% 
      group_by(rule3) %>% 
      summarise(subrules3 = paste(Subrule, collapse = ","))) %>% 
  mutate(rule4 = row.names(tree4$frame)[tree4$where]) %>%
      left_join(rpart.rules.table(tree4) %>% 
      filter(Leaf == TRUE) %>% 
      rename(rule4 = Rule) %>% 
      group_by(rule4) %>% 
      summarise(subrules4 = paste(Subrule, collapse = ",")))
fancyRpartPlot(tree3, digits = -3, sub = "", palettes = "Blues", type = 2)

plotcp(tree3)

Predicting coverage at the parrish level

The simple model below, tree2, shows which variables best predict whether a parrish has been reached by humanitarian agencies or not This is not to imply that this actually depicts the decision-making process of our partners, just that these are the factors towards which we, as a reponse, are predisposed.

To understand the plot below, all parrishes have been split into four groups (the terminal nodes at the bottom marked [4], [5], [6] and [7]) based on the percentage of parrishes in each node where humanitarian agencies are present. Each bubble has three figures – the one on the top shows the percentage of parishes in each group that has a humanitarian presence: for instance, the root, at the top and marked [1], shows that on average, 0.547 or 54.7% of all parrishes have humanitarian agencies present in them. The next numbers, “n = 1161” show that 1161 parrishes are in that group and the percentage of parrishes in that group.

fancyRpartPlot(tree2, digits = -3, sub = "", palettes = "Blues", type = 2)

We come away with a slightly unfavourable view of our operational footprint. We are most present in parrishes which are both more urban and more dense – being present in 83% of parrishes which are more than 79% urban and have more than 187 people per km2 (this applies to the 337 parrishes in node [7]). Perhaps it is understandable that the most heavily populated parrishes have greater organisational presence. But it must be mentioned that population density and urban population are both negatively correlated with poverty incidence. In the next section, we

The largest determinants of the number of beneficiaries reached per parrish are population density and percentage urban, as beneficiary numbers tend to scale in line with larger populations.

Characteristics of the population not covered

Instead of a singular prioritisation score, which is typically the weighted average of several secondary data indicators, a tree is better at taking into account the various priorities and limitations of each partner – some might not have the capacity to expand outside of urban areas, other have specific geographic biases – and decision trees are a useful tool to make the best targetting decisions one can within one’s constraints.

With that in mind, tree3 was developed to aid future prioritisation. The independent variable it strives to predict is the poverty score (unhide code in section xx to see its specific calculation), which, as mentioned, is just the rescaled average of number of poor persons and poverty incidence. Tree3’s performance was considered superior to tree1 by the analyst, which just used the absolute number of poor persons as its independent variable, due to its ability to clearly distinguish its groups of parrishes

fancyRpartPlot(tree4, digits = -3, sub = "", palettes = "Blues", type = 2)

# figure out the right order for the leaves
# I'm liking tree3 more and more
  
parr0 %>% 
  group_by(rule3) %>% 
  summarise(parr_no_ben = n_distinct(pcode3[beneficiarios == 0]),
            beneficiarios = sum(beneficiarios),
            ben_per_parr = sum(beneficiarios) / n(), 
            not_covered = sum(not_covered_pobre),
            nc_per_parr = sum(not_covered_pobre) / n(),
            avg_org_count = mean(org_count),
            avg_poblacion = mean(poblacion_2019),
            coverage_percent = sum(beneficiarios) / sum(poblacion_2019),
            percent_pobre = sum(pob_pobre) / sum(poblacion_2019),
            percent_urbana = sum(pob_urbana) / sum(poblacion_2019),
            densidad_ppl_km2 = sum(poblacion_2019) / sum(area_km2, na.rm = TRUE),
            parroquias = n(),
            municipios = n_distinct(pcode2),
            parr_per_mun = n() / n_distinct(pcode2)) %>% 
  gather(key = var_name, value = value, 2:ncol(.)) %>% 
  spread_(key = names(.)[1], value = 'value') %>% 
  arrange(factor(var_name, levels = c("not_covered", "nc_per_parr", "avg_poblacion", 
                                      "beneficiarios",
                                      "ben_per_parr",  "avg_org_count", 
                                      "coverage_percent",
                                      "percent_pobre", "percent_urbana", "densidad_ppl_km2", 
                                      "parroquias", "parr_no_ben", "municipios", 
                                      "parr_per_mun"))) %>%  
  
  pander(big.mark = ",")
var_name 4 5 6 7
not_covered 1,091,079 6,374,829 3,648,710 522,263
nc_per_parr 8,659 12,905 9,653 5,223
avg_poblacion 46,126 35,806 19,120 7,174
beneficiarios 176,330 349,684 111,813 17,452
ben_per_parr 1,399 707.9 295.8 174.5
avg_org_count 2.468 1.63 0.9471 0.39
coverage_percent 0.03034 0.01977 0.01547 0.02433
percent_pobre 0.2181 0.3802 0.5203 0.7524
percent_urbana 0.9895 0.9251 0.7535 0.2336
densidad_ppl_km2 996.1 147.4 18.07 1.855
parroquias 126 494 378 100
parr_no_ben 38 212 205 76
municipios 60 233 187 61
parr_per_mun 2.1 2.12 2.021 1.639
# 4 is population centres which are easy to reach, but with only 24% of the population being poor, 
# careful targetting and beneficiary selection is required. 
# 5 is probably the best option for expansion -- it has the highest concentration of poor persons not covered per parrish, is substantially poorer than A (with a 40% poverty incidence, making targetting of vulnerable persons much easier). Additionally, the parrishes within this group are still very urbanised (91%)
# C is probably the best option for expansion -- it has the highest concentration of unconvered 
# persons per parroquia and municipio, is substantially poorer than A (at 43% poverty incidence). 
# Operational expansion is more likely, due to the higher concentration of organisations and 
# it is also fairly urban, meaning that this uncovereved population is fairly easy to reach. 
# better than B in almost every way -- higher concentration of NC, less area to cover and 
# it's already got higher operational coverage, so that makes; 
# in fact, B should be prioritised here -- it's easy to 
# in many ways, D is better than C as well
# E is just a giant operational challenge

Unhide for tree1 notes – move this to appendix

# V is dense, urban and highest operational presence, shortly followed by W
# Z is a priority for reaching the most vulnerable and marginalised, 
# but it truly is very sparsely populated. The number of persons you can reach is low and 
# this is the most operationally challenging
# Y is more than 50% poor, but also sparsely populated; but it has more not_covered than X,  with double the number of not_covered per pcode3, it also has less than half the 
# municipalities -- operationally more feasible to move into this area
# X is spread out, numerous and you should expand there only if you have operations in adjacent areas

parr0 %>% 
  group_by(rule1) %>% 
  summarise(parr_no_ben = n_distinct(pcode3[beneficiarios == 0]), 
            beneficiarios = sum(beneficiarios),
            ben_per_parr = sum(beneficiarios) / n(), 
            not_covered = sum(not_covered_pobre),
            nc_per_parr = sum(not_covered_pobre) / n(),
            nc_per_mun = sum(not_covered_pobre) / n_distinct(pcode2), 
            avg_org_count = mean(org_count),
            coverage_percent = sum(beneficiarios) / sum(poblacion_2019),
            percent_pobre = sum(pob_pobre) / sum(poblacion_2019),
            percent_urbana = sum(pob_urbana) / sum(poblacion_2019),
            densidad_ppl_km2 = sum(poblacion_2019) / sum(area_km2, na.rm = TRUE),
            parroquias = n(),
            municipios = n_distinct(pcode2),
            parr_per_mun = n() / n_distinct(pcode2)) %>% 
  gather(key = var_name, value = value, 2:ncol(.)) %>% 
  spread_(key = names(.)[1], value = 'value') %>% 
  arrange(factor(var_name, levels = c("not_covered", "nc_per_parr", "nc_per_mun", "beneficiarios",
                                      "ben_per_parr",  "avg_org_count", "coverage_percent",
                                      "percent_pobre", "percent_urbana", "densidad_ppl_km2", 
                                      "parroquias", "parr_no_ben", "municipios", 
                                      "parr_per_mun"))) %>%  pander(big.mark = ",")
var_name 14 15 2 6
not_covered 270,551 2,023,276 5,130,239 4,212,814
nc_per_parr 12,298 59,508 6,413 17,408
nc_per_mun 24,596 87,969 18,128 45,791
beneficiarios 9,788 25,392 177,358 442,741
ben_per_parr 444.9 746.8 221.7 1,830
avg_org_count 1.636 2.559 0.8325 2.992
coverage_percent 0.007524 0.005169 0.01651 0.03056
percent_pobre 0.2155 0.417 0.4939 0.3214
percent_urbana 0.9884 0.9714 0.684 0.9885
densidad_ppl_km2 1,751 725.9 12.04 1,151
parroquias 22 34 800 242
parr_no_ben 8 4 471 48
municipios 11 23 283 92
parr_per_mun 2 1.478 2.827 2.63
pcode3_shape <- st_read("C:/Users/Sean Ng/Documents/R/coverage_gaps_venezuela/ven_admbnda_adm3_20180502/ven_admbnda_adm3_20180502.shp",
                        quiet = TRUE) %>% 
  rename(pcode1 = ADM1_PCODE,
         pcode2 = ADM2_PCODE,
         pcode3 = ADM3_PCODE)



unique(parr$estado)
##  [1] "DISTRITO CAPITAL" "AMAZONAS"         "ANZOATEGUI"       "APURE"           
##  [5] "ARAGUA"           "BARINAS"          "BOLIVAR"          "CARABOBO"        
##  [9] "COJEDES"          "DELTA AMACURO"    "FALCON"           "GUARICO"         
## [13] "LARA"             "MERIDA"           "MIRANDA"          "MONAGAS"         
## [17] "NUEVA ESPARTA"    "PORTUGUESA"       "SUCRE"            "TACHIRA"         
## [21] "TRUJILLO"         "YARACUY"          "ZULIA"            "VARGAS"
parr0 %>% filter(percent_pobre >= 0.697) %>% 
  summarise(parroquias_ben = length(pcode3[beneficiarios > 0]),
            parrooquias = n())
## # A tibble: 1 x 2
##   parroquias_ben parrooquias
##            <int>       <int>
## 1             55         134
# for showing the output of the tree nicely
print(tree3)
## n= 1098 
## 
## node), split, n, deviance, yval
##       * denotes terminal node
## 
## 1) root 1098 43.671140 0.2579346  
##   2) percent_sin_agua_segura< 0.1899 620 16.525820 0.2141432  
##     4) percent_sin_agua_segura< 0.0256 126  2.642949 0.1350523 *
##     5) percent_sin_agua_segura>=0.0256 494 10.181350 0.2335573 *
##   3) percent_sin_agua_segura>=0.1899 478 16.542390 0.3145820  
##     6) percent_sin_saneamiento_mejorado< 0.4797 378 10.542770 0.2919355 *
##     7) percent_sin_saneamiento_mejorado>=0.4797 100  2.588773 0.3954017 *
printcp(tree3)
## 
## Regression tree:
## rpart(formula = poverty_score ~ estado + percent_urbana + densidad_ppl_km2 + 
##     razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total + 
##     percent_sin_agua_segura + percent_sin_saneamiento_mejorado + 
##     percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina, 
##     data = ., weights = promedio_de_personas_por_vivienda, cp = 0.044)
## 
## Variables actually used in tree construction:
## [1] percent_sin_agua_segura          percent_sin_saneamiento_mejorado
## 
## Root node error: 43.671/1098 = 0.039773
## 
## n= 1098 
## 
##         CP nsplit rel error  xerror     xstd
## 1 0.242790      0   1.00000 1.00186 0.027207
## 2 0.084759      1   0.75721 0.77251 0.023792
## 3 0.078103      2   0.67245 0.71361 0.022856
## 4 0.044000      3   0.59435 0.63949 0.022120

Tree1 splits parroquias by

LS0tDQp0aXRsZTogIlJlcG9ydCBvbiBjb3ZlcmFnZSBhbmQgZ2FwcyBpbiB0aGUgaHVtYW5pdGFyaWFuIHJlc3BvbnNlIGluIFZlbmV6dWVsYSINCmF1dGhvcjogIlNlYW4gTmciDQpkYXRlOiAiMjUvMTEvMjAyMSINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgDQotLS0NCg0KPHN0eWxlPg0KICAgIGJvZHkgLm1haW4tY29udGFpbmVyIHsNCiAgICAgICAgbWF4LXdpZHRoOiAxODAwcHg7DQogICAgfQ0KPC9zdHlsZT4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy53aWR0aD05LjUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz1GQUxTRSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoc3RyaW5naSkNCmxpYnJhcnkoc3RyaW5ncikNCg0KbGlicmFyeShwYW5kZXIpDQpsaWJyYXJ5KERUKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ2dtYXApDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkoZ2dmb3JjZSkNCmxpYnJhcnkoZ2dwdWJyKQ0KbGlicmFyeShmb3JjYXRzKQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KHJhdHRsZSkNCmxpYnJhcnkocnBhcnQpDQpsaWJyYXJ5KHJwYXJ0LnBsb3QpDQpsaWJyYXJ5KHJwYXJ0LnV0aWxzKQ0KbGlicmFyeShwYXJ0eWtpdCkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KGZhY3RvZXh0cmEpDQpsaWJyYXJ5KHNoaW55KQ0KDQojIGRpc2FibGluZyBzY2llbnRpZmljIG5vdGF0aW9uDQpvcHRpb25zKHNjaXBlbiA9IDEwMCkNCg0KIyBwYW5kZXIgdGFibGVzIGFsbCBpbiBvbmUgcm93DQpwYW5kZXJPcHRpb25zKCd0YWJsZS5zcGxpdC50YWJsZScsIEluZikNCg0KIyBwYW5kZXIgdGhvdXNhbmRzIHNlcGFyYXRvcg0KcGFuZGVyT3B0aW9ucygiYmlnLm1hcmsiLCAiLCIpDQpgYGANCg0KIyBSZXBvcnQgb24gY292ZXJhZ2UgYW5kIGdhcHMgaW4gdGhlIHJlc3BvbnNlIHRvIHRoZSBWZW5lenVlbGEgTWlncmFudCBhbmQgRWNvbm9taWMgQ3Jpc2lzLCAyMDE5DQoNCj4gVGhpcyBjb3ZlcmFnZSBhbmQgZ2FwcyBhbmFseXNpcyBpcyBpbnRlbmRlZCB0byBhbmFseXNlIGFuZCBwcm92aWRlIHJlY29tbWVuZGF0aW9ucyBvbiBob3cgYmVzdCB0byByZWFjaCBwb3B1bGF0aW9ucyBpbiBuZWVkIG5vdCBjdXJyZW50bHkgY292ZXJlZCBieSBodW1hbml0YXJpYW4gYWN0aW9uLiBUaGlzIGlzIGFuIGF1dG9tYXRlZCByZXBvcnRlZCBpbnRlbmRlZCB0byBzZXJ2ZSBhcyBhIHRlbXBsYXRlIGZvciBjb3ZlcmFnZSBhbmQgZ2FwcyBhbmFseXNlcy4gRGF0YSBvcmlnaW5hdGVzIGZyb20gdGhlIEVkdWNhdGlvbiwgSGVhbHRoLCBOdXRyaXRpb24sIFByb3RlY3Rpb24gYW5kIFdBU0ggQ2x1c3RlcnMgZnJvbSAyMDE5LiBQYXJ0bmVyIGRhdGEgaGFzIGJlZW4gYW5vbnltaXNlZC4gDQoNCj4gQ292ZXJhZ2UgYW5kIGdhcHMgYW5hbHlzZXMgYXJlIGtleSBkb2N1bWVudHMsIGJ1dCBhcmUgYWxzbyByYXJlbHkgdGFrZW4gaW50byBhY2NvdW50IGR1cmluZyBzdHJhdGVnaWMgcGxhbm5pbmcgb3IgcmVmZXJlbmNlZCBpbiByZXZpc2lvbnMgb2YgbWFqb3IgZ3VpZGluZyBkb2N1bWVudHMsIHN1Y2ggYXMgSFJQcy4gVGhleSBhcmUgbm90IG1lbnRpb25lZCBpbiBPQ0hBJ3MgSHVtYW5pdGFyaWFuIFJlc3BvbnNlIFBsYW5uaW5nIGd1aWRhbmNlLiBBbmQgaXQgcmVtYWlucyBhbiBpbmR1c3RyeS13aWRlIGNoYWxsZW5nZSB0byByZXNwb25kIGFuZCBhZGFwdCB0byBnYXBzIGluIGNvdmVyYWdlIGFuZCByZWFsbG9jYXRlIHJlc291cmNlcyBhY2NvcmRpbmdseS4gDQoNCiMjIyMgUmVhZGluZyBpbiB0aGUgZGF0YSBhbmQgZG9pbmcgdGhlIGluaXRpYWwgY2xlYW5pbmcNCg0KVW5saWtlIHRoZSBkb2N1bWVudCBvZiA1VyByZXBvcnRpbmcgYW5kIGNsZWFuaW5nLCB3ZSB3aWxsIG5vdCBiZSBleHBsb3JpbmcgdGhlIGNsZWFuaW5nIHByb2Nlc3MuIEJ1dCB5b3UgY2FuIHVuaGlkZSBhbnkgb2YgdGhlIGNvZGUgY2h1bmtzIHRvIHNlZSB0aGUgZGV0YWlscyBieSBjbGlja2luZyB0aGUgIkNvZGUiIGJ1dHRvbi4gDQoNCmBgYHtyIHJlYWRpbmctYW5kLWNsZWFuaW5nfQ0KDQojIGZ1bmN0aW9uIHRvIHJlbW92ZSBhY2NlbnRzIA0Kcm1fYWNjZW50IDwtIGZ1bmN0aW9uKGNvbG5zKXsNCiAgY29sbnMgPC0gc3RyaV90cmFuc19nZW5lcmFsKGNvbG5zLCAiTGF0aW4tQVNDSUkiKQ0KfQ0KDQojIHJlYWRpbmcgYW5kIGNsZWFuaW5nIC0tIHlvdSByZWFsbHkgc2hvdWxkIGJyZWFrIGl0IGludG8gcGFydHMNCnZlbjEgPC0gcmVhZF9jc3YoImNvbnNvbGlkYXRpb24gMTkxMjA5IDE2MzUuY3N2IikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JSANCiAgIyByZW1vdmluZyB1bnVzZWQgY29sdW1ucw0KICBzZWxlY3QoLWMoY29kaWdvZGVlc3RhYmxlY2ltaWVudG9vY2VudHJvLCBsb2NfaWQsIGhycF9zaXRyZV9wX2luZGljYXRvciwgDQogICAgICAgICAgICB0aXBvZGVyZXNwdWVzdGEsIGNvbWVudGFyaW9zLCBjb29yZGVhZGFzX2dwc194LCBjb29yZGVhZGFzX2dwc195LA0KICAgICAgICAgICAgZmVjaGFkZV9pbmljaW8sIGZlY2hhX3ByZXZpc3RhZGVfZmluYWxpemFjaW9uKSkgJT4lIA0KICAjIHJlbmFtaW5nIHVud2llbGR5IGNvbHVtbnMgDQogIHJlbmFtZSh1YmljYWNpb24gICAgICAgICAgPSBjb211bmlkYWRvbm9tYnJlZGVsZXN0YWJsZWNpbWllbnRvX2NlbnRybywgDQogICAgICAgICBzZWN0b3IgICAgICAgICAgICAgPSBzZWN0b3JfYXJlYWRlX3Jlc3BvbnNhYmlsaWFkLA0KICAgICAgICAgYmVuZWZpY2lhcmlvc19tZXRhID0gYmVuZWZpY2lhcmlvc19tZXRhX251bWVyb2RlcGVyc29uYXMsDQogICAgICAgICBlc3RhdHVzICAgICAgICAgICAgPSBlc3RhdHVzZGVwcm9ncmFtYWNpb24pICU+JSANCiAgICAgICMgbXV0YXRpbmcgdGhlIGRhdGUgdG8gdGhlIHJpZ2h0IGZvcm1hdA0KICBtdXRhdGUobW9udGggPSBhcy5mYWN0b3IocmVjb2RlKG1vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDRgID0gIjMwLzA0LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDVgID0gIjMxLzA1LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDZgID0gIjMwLzA2LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDdgID0gIjMxLzA3LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDhgID0gIjMxLzA4LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDlgID0gIjMwLzA5LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDEwYCA9ICIzMS8xMC8yMDE5IikpKSAlPiUgDQogIG11dGF0ZShtb250aCA9IGFzLkRhdGUobW9udGggJT4lIHN0cnB0aW1lKC4sIGZvcm1hdCA9ICIlZC8lbS8lWSIpKSkgJT4lIA0KICBtdXRhdGUob3JnX2xpZGVyID0gY29hbGVzY2Uob3JnX2xpZGVyLCBvcmdfaW1wbGVtZW50YWRvcmEpKSAlPiUgDQogICMgY29ycmVjdGluZyBzZWN0b3IgbmFtZXMNCiAgbXV0YXRlKHNlY3RvciA9IHN0cl9yZXBsYWNlX2FsbChzZWN0b3IsIGMoDQogICAgIkFndWFfc2FuZWFtaWVudG9faGlnaWVuZSIgICAgICAgICAgICA9ICJXQVNIIiwNCiAgICAiZWR1Y2FjaW9uIiAgICAgICAgICAgICAgICAgICAgICAgICAgID0gIkVkdWNhY2lvbiIsDQogICAgIk51dHJpY2lvbiIgICAgICAgICAgICAgICAgICAgICAgICAgICA9ICJOdXRyaWNpb24iLA0KICAgICJwcm90ZWNjacOzbl9OacOxb3NfTmnDsWFzX0Fkb2xlc2NlbnRlcyIgPSAiUHJvdGVjY2lvbl9OTkEiLA0KICAgICJQcm90ZWNjacOzbl9OacOxb3NfTmnDsWFzX0Fkb2xlc2NlbnRlcyIgPSAiUHJvdGVjY2lvbl9OTkEiLA0KICAgICJQcm90ZWNjacOzbl9WaW9sZW5jaWFfR8OpbmVybyIgICAgICAgICA9ICJQcm90ZWNjaW9uX0dCViIpKSkgJT4lIA0KICAjIHJlbmFtaW5nIGJlbmVmaWNpYXJ5IGRpc2FnZ3JlZ2F0aW9uIGNvbHVtbnMgDQogIHJlbmFtZShmXzBfMTggPSBmXzE4LA0KICAgICAgICAgbV8wXzE4ID0gbV8xOCwNCiAgICAgICAgIGZfMThwbHVzID0gZl8xOF8yLA0KICAgICAgICAgbV8xOHBsdXMgPSBtXzE4XzIpICU+JSANCiAgbXV0YXRlKGVzdGFkbyAgICA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIoZXN0YWRvKSksIA0KICAgICAgICAgbXVuaWNpcGlvID0gcm1fYWNjZW50KHN0cl90b191cHBlcihtdW5pY2lwaW8pKSwNCiAgICAgICAgIHBhcnJvcXVpYSA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIocGFycm9xdWlhKSksDQogICAgICAgICB1YmljYWNpb24gPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKHViaWNhY2lvbikpLA0KICAgICAgICAgYWN0aXZpZGFkID0gcm1fYWNjZW50KHN0cl90b191cHBlcihhY3RpdmlkYWQpKSwNCiAgICAgICAgIGNhdGVnb3JpYSA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIoY2F0ZWdvcmlhZGVhY3RpdmlkYWQpKSkgJT4lIA0KICAjIHJlY29kaW5nIHRoZSBlc3RhdHVzIGNvbHVtbiANCiAgbXV0YXRlKGVzdGF0dXMgPSBzdHJfcmVwbGFjZV9hbGwoZXN0YXR1cywgDQogICAgICAgICAgICAgICAgICBjKCJFbiBlamVjdWNpb24iID0gImVqZWN1Y2lvbiIsIA0KICAgICAgICAgICAgICAgICAgICAiZW4gZWplY3VjacOzbiIgPSAiZWplY3VjaW9uIiwgDQogICAgICAgICAgICAgICAgICAgICJlbiBFamVjdWNpw7NuIiA9ICJlamVjdWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAiRW4gZWplY3VjacOzbiIgPSAiZWplY3VjaW9uIiwNCiAgICAgICAgICAgICAgICAgICAgIkVuIEVqZWN1Y2nDs24iID0gImVqZWN1Y2lvbiIsDQogICAgICAgICAgICAgICAgICAgICJFbmVqZWN1Y2nDs24iICA9ICJlamVjdWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAiNDM3NDEiICAgICAgICA9ICJlamVjdWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAiZmluYWxpemFkYSIgPSAiZmluYWxpemFkYSIsDQogICAgICAgICAgICAgICAgICAgICJGaW5hbGl6YWRhIiA9ICJmaW5hbGl6YWRhIiwNCiAgICAgICAgICAgICAgICAgICAgIlBsYW5lYWRhIiA9ICJwbGFuZWFkYSIsDQogICAgICAgICAgICAgICAgICAgICJwbGFuZWFkYSBjb24gZmluYW5jaWFtaWVudG8iID0gInBsYW5lYWRhIiwNCiAgICAgICAgICAgICAgICAgICAgInBsYW5lYWRhIHNpbiBmaW5hbmNpYW1pZW50byIgPSAicGxhbmVhZGEiKSkpICU+JSANCiAgcmVwbGFjZV9uYShsaXN0KGVzdGF0dXMgPSAiZWplY3VjaW9uIikpICU+JSANCiAgIyByZW1vdmluZyBhbGwgcGxhbm5lZCBhY3Rpdml0aWVzIA0KICBmaWx0ZXIoZXN0YXR1cyAhPSAicGxhbmVhZGEiKSAlPiUgDQogIGZpbHRlcihzdHJfZGV0ZWN0KHBjb2RlMywgIl5WRSIpKSAlPiUgIyBkZWNpZGUgaWYgeW91IHdhbnQgdG8gZG8gdGhpcyBoZXJlIG9yIGxhdGVyDQogIHNlbGVjdCgtYygyMzo5MikpDQoNCg0KYGBgDQoNCmBgYHtyIG91dHB1dHMtY2xlYW5pbmd9DQojIEknbSBraW5kYSBkb3VidGluZyB0aGUgdXNlIG9mIHVfYmVuLCB5YSBJIHRoaW5rIHRha2UgaXQgb3V0PyBzaW5jZSB5b3UncmUgb25seSB1c2luZyBpdCBvbmNlDQojIEFtIEkganVzdCBtYWtpbmcgdGhlc2Ugb3V0IG9mIGhhYml0PyBJIGNvdWxkIGN1dCB0aGVtIGFuZCBtYWtlIHRoZW0gaW5zaWRlIHRoZSANCiMgY29kZSBjaHVuayBmb3IgcGFyciwgYnV0IG1heWJlIEkgY2FuIGZpbmQgc29tZSBqdXN0aWZpY2F0aW9uIGZvciB0aGVpciBleGlzdGVuY2UsIA0KIyBtYXliZSB0aGUgZGlzYWdncmVnYXRpb25zPyANCg0KIyBWYWNjaW5hdGlvbiBhY3Rpdml0aWVzIGZpbHRlcmVkIG91dA0KdV9iZW4gPC0gdmVuMSAlPiUgDQogIHBpdm90X2xvbmdlcihmXzBfMTg6bV8xOHBsdXMsIG5hbWVzX3RvID0gImRlc2FncmVnYWNpb24iLCB2YWx1ZXNfdG8gPSAiYmVuZWZpY2lhcmlvcyIpICU+JSANCiAgZmlsdGVyKGNhdGVnb3JpYWRlYWN0aXZpZGFkICE9ICJWYWN1bmFjaW9uIikgJT4lIA0KICBmaWx0ZXIoYmVuZWZpY2lhcmlvcyAhPSAwKSAlPiUgDQogIGdyb3VwX2J5KHViaWNhY2lvbiwgZGVzYWdyZWdhY2lvbikgJT4lIA0KICBzbGljZSh3aGljaC5tYXgoYmVuZWZpY2lhcmlvcykpICU+JSANCiAgdW5ncm91cCgpDQoNCmFjdF9iZW4gPC0gdmVuMSAlPiUgDQogIHBpdm90X2xvbmdlcihmXzBfMTg6bV8xOHBsdXMsIG5hbWVzX3RvID0gImRlc2FncmVnYWNpb24iLCB2YWx1ZXNfdG8gPSAiYmVuZWZpY2lhcmlvcyIpICU+JSANCiAgZmlsdGVyKGJlbmVmaWNpYXJpb3MgIT0gMCkgJT4lIA0KICBncm91cF9ieSh1YmljYWNpb24sIGRlc2FncmVnYWNpb24sIGFjdGl2aWRhZCkgJT4lIA0KICBzbGljZSh3aGljaC5tYXgoYmVuZWZpY2lhcmlvcykpICU+JSANCiAgdW5ncm91cCgpDQoNCiMgcmJpbmQoc3VtKHVfYmVuJGJlbmVmaWNpYXJpb3MpLCANCiMgICAgICAgc3VtKGFjdF9iZW4kYmVuZWZpY2lhcmlvcyksIA0KIyAgICAgICBzdW0odV9iZW4kYmVuZWZpY2lhcmlvcykgLSBzdW0oYWN0X2JlbiRiZW5lZmljaWFyaW9zKSkNCg0KYGBgDQoNCmBgYHtyIG1ha2luZy1hbGwtcGFycn0NCiMgSSB0aGluayB0aGlzIGlzIGEgZ2lnYW50aWMgY2h1bmsgLS0gY2Fubm90IGRlY2lkZSBpZiBJIHdvdWxkIHJhdGhlciBoYXZlIGxlc3MgdGhpbmdzIGluIHRoZSANCiMgZW52aXJvbm1lbnQgb3IgaWYgSSB3YW50IG1vcmUgcmVhZGFibGUgY2h1bmtzLiBUaGUgYmVuZWZpdCBoZXJlIEkgZ3Vlc3MgaXMgdGhhdCBpZiBJIHdhbnQgdG8gY2hhbmdlIHNvbWV0aGluZywgSSBqdXN0IGhhdmUgdG8gY29tZSB0byB0aGlzIGNodW5rDQoNCnBhcnIgPC0gdV9iZW4gJT4lIA0KICBncm91cF9ieShwY29kZTMpICU+JSANCiAgc3VtbWFyaXNlKGJlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcykpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgbGVmdF9qb2luKGFjdF9iZW4gJT4lIA0KICAgICAgICAgICAgIGZpbHRlcihjYXRlZ29yaWEgIT0gIlZhY3VuYWNpb24iKSAlPiUNCiAgICAgICAgICAgICBncm91cF9ieSh1YmljYWNpb24sIGRlc2FncmVnYWNpb24sIHNlY3RvcikgJT4lIA0KICAgICAgICAgICAgICAgIHNsaWNlKHdoaWNoLm1heChiZW5lZmljaWFyaW9zKSkgJT4lIA0KICAgICAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUgDQogICAgICAgICAgICAgICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHNlY3RvciwgdmFsdWVzX2Zyb20gPSBiZW5lZmljaWFyaW9zKSAlPiUgDQogICAgICAgICAgICAgICAgZ3JvdXBfYnkocGNvZGUzKSAlPiUgDQogICAgICAgICAgICAgICAgIyBnZXR0aW5nIHNlY3RvciB0b3RhbHMgcGVyIHBjb2RlMw0KICAgICAgICAgICAgICAgIHN1bW1hcmlzZShlZHVjYWNpb25fYmVuID0gc3VtKEVkdWNhY2lvbiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgbnV0cmljaW9uX2JlbiA9IHN1bShOdXRyaWNpb24sIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlY2Npb25HQlZfYmVuID0gc3VtKFByb3RlY2Npb25fR0JWLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWNjaW9uR2VuZXJhbF9iZW4gPSBzdW0oUHJvdGVjY2lvbl9HZW5lcmFsLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWNjaW9uTk5BX2JlbiA9IHN1bShQcm90ZWNjaW9uX05OQSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2FsdWRfYmVuID0gc3VtKFNhbHVkLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBzZWd1cmlkYWRfYWxpbWVudGFyaWFfYmVuID0gc3VtKFNlZ3VyaWRhZF9BbGltZW50YXJpYSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgd2FzaF9iZW4gPSBzdW0oV0FTSCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnX2NvdW50ID0gbl9kaXN0aW5jdChvcmdfaW1wbGVtZW50YWRvcmEpKSAlPiUgDQogICAgICAgICAgICAgdW5ncm91cCgpKSAlPiUgDQogIGZpbHRlcihzdHJfZGV0ZWN0KHBjb2RlMywgIl5WRSIpKSAlPiUgDQogICMgcmlnaHRfam9pbiB0byB0aGUgY2Vuc3VzIGRhdGENCiAgcmlnaHRfam9pbihyZWFkX2V4Y2VsKCJjZW5zdXMgZGF0YSAyMDE5MTEyMi54bHN4Iiwgc2hlZXQgPSAiZGF0YSIpICU+JSANCiAgICAgICAgY2xlYW5fbmFtZXMoKSAlPiUgDQogICAgICAgICMgc2VsZWN0aW5nIHZhcmlhYmxlcyBhbmQgcmVuYW1pbmcgdGhlbSB3aXRoIHNlbGVjdA0KICAgICAgICBzZWxlY3QoZXN0YWRvLCBwY29kZTEsIG11bmljaXBpbywgcGNvZGUyLCBwYXJyb3F1aWEsIHBjb2RlMywgDQogICAgICAgICAgICAgICBmbyA9IGZpZWxkX29mZmljZSwNCiAgICAgICAgICAgICAgIHBvYmxhY2lvbl8yMDE5ID0geF8yMDE5X3BvYmxhY2lvbl9wYXJyb3F1aWFsX3RvdGFsLA0KICAgICAgICAgICAgICAgaG9nYXJlc18yMDExID0gbnVtZXJvX2RlX2hvZ2FyZXMsIA0KICAgICAgICAgICAgICAgaGFtXzIwMTlfYW1iaXRvc19nZSwgDQogICAgICAgICAgICAgICBwZXJjZW50X3BvYnJlID0gaGFtXzIwMTlfeHhfcG9icmV6YV9lbnZfcG9yX3BhcnJvcXVpYSwgDQogICAgICAgICAgICAgICBwb2JfcG9icmUgPSBoYW1fMjAxOV94eF9wb2JsYWNpb25fcG9icmVfcG9yX3BhcnJvcXVpYSwgDQogICAgICAgICAgICAgICBwb2JsYWNpb25fdG90YWxfMjAxMSwNCiAgICAgICAgICAgICAgIHBvYmxhY2lvbl9pbmZhbnRpbF9tZW5vcl9kZV8xMl9hbm9zLCBwb2JsYWNpb25fYWRvbGVzY2VudGVzX2RlXzEyX2FfMTdfYW5vcywNCiAgICAgICAgICAgICAgIHBvYmxhY2lvbl9kZV8xOF9hbm9zX3lfbWFzLCANCiAgICAgICAgICAgICAgIHBlcmNlbnRfdXJiYW5hID0gcG9ibGFjaW9uX3VyYmFuYV9wZXJjZW50LCANCiAgICAgICAgICAgICAgIGFyZWFfa20yLCANCiAgICAgICAgICAgICAgIGRlbnNpZGFkX3BwbF9rbTIgPSBkZW5zaWRhZF9wb2JsYWNpb25hbF9wcGxfa20yLA0KICAgICAgICAgICAgICAgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX2luaWNpYWwsIG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9wcmltYXJpYSwgDQogICAgICAgICAgICAgICBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fbWVkaWEsIHJhem9uX2RlX2RlcGVuZGVuY2lhX3RvdGFsLA0KICAgICAgICAgICAgICAgcmF6b25fZGVfZGVwZW5kZW5jaWFfZGVfbWVub3Jlc19kZV8xNV9hbm9zLCANCiAgICAgICAgICAgICAgIHBlcmNlbnRfc2luX2FndWFfc2VndXJhID0geF9hYmFzdF9hZ3VhMl9wZXJjZW50X3Npbl9hZ3VhX3NlZ3VyYSwNCiAgICAgICAgICAgICAgIHBlcmNlbnRfc2luX3NhbmVhbWllbnRvX21lam9yYWRvID0NCiAgICAgICAgICAgICAgICAgeF9zYW5lYW1pZW50b19wZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbywNCiAgICAgICAgICAgICAgIHBlcmNlbnRfYW5hbGZhYmV0byA9IHBlcmNlbnRfcG9ibGFjaW9uXzEwX2Fub3NfeV9tYXNfYW5hbGZhYmV0YSwNCiAgICAgICAgICAgICAgIHByb21lZGlvX2RlX3BlcnNvbmFzX3Bvcl92aXZpZW5kYSwNCiAgICAgICAgICAgICAgIHBlcmNlbnRfaG9nYXJlc19qZWZhdHVyYV9mZW1lbmluYSA9IHBlcmNlbnRfZGVfaG9nYXJlc19jb25famVmYXR1cmFfZmVtZW5pbmEsDQogICAgICAgICAgICAgICBwZXJjZW50X3Npbl9zZXJ2aWNpb19lbGVjdHJpY28gPQ0KICAgICAgICAgICAgICAgICBzZXJ2aWNpb19lbGVjdHJpY29fcGVyY2VudF9ub190aWVuZV9zZXJ2aWNpb19lbGVjdHJpY28sDQogICAgICAgICAgICAgICBoYW1fMjAxOV94X3Zpb2xlbmNpYV9lbnZlbG9wZSwgaGFtXzIwMTlfeF9tb3J0YWxpZGFkX3lfc2FsdWRfZW52ZWxvcGUsIA0KICAgICAgICAgICAgICAgaGFtXzIwMTlfeF9wb2JyZXphX2VudmVsb3BlLCBwcm9tZWRpb19kZV9lZGFkKSAlPiUgDQogICAgICAgIG11dGF0ZShlc3RhZG8gICAgID0gcm1fYWNjZW50KHN0cl90b191cHBlcihlc3RhZG8pKSwgIyBqdXN0IHRvIG1ha2Ugc3VyZSANCiAgICAgICAgICAgICAgIG11bmljaXBpbyAgPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKG11bmljaXBpbykpLA0KICAgICAgICAgICAgICAgcGFycm9xdWlhICA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIocGFycm9xdWlhKSkpICU+JSANCiAgICAgICAgIyBjcmVhdGluZyBuZXcgZGlzYWdncmVnYXRpb24gdmFyaWFibGVzIA0KICAgICAgICBtdXRhdGUocG9iX21lbm9yX2RlXzE4ID0gKHBvYmxhY2lvbl9pbmZhbnRpbF9tZW5vcl9kZV8xMl9hbm9zICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvYmxhY2lvbl9hZG9sZXNjZW50ZXNfZGVfMTJfYV8xN19hbm9zKSAvcG9ibGFjaW9uX3RvdGFsXzIwMTEgKg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9ibGFjaW9uXzIwMTksIA0KICAgICAgICAgICAgICAgcG9iXzE4X3lfbWFzICAgID0gcG9ibGFjaW9uX2RlXzE4X2Fub3NfeV9tYXMgLyBwb2JsYWNpb25fdG90YWxfMjAxMSAqIHBvYmxhY2lvbl8yMDE5LCANCiAgICAgICAgICAgICAgIGhvZ2FyZXNfMjAxOSAgICA9IGhvZ2FyZXNfMjAxMSAqIHBvYmxhY2lvbl8yMDE5IC8gcG9ibGFjaW9uX3RvdGFsXzIwMTEsIA0KICAgICAgICAgICAgICAgbWF0cmljdWxhX3RvdGFsID0gbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX2luaWNpYWwgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9wcmltYXJpYSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX21lZGlhKSAlPiUgDQogICAgICAgICMgZGl2aWRpbmcgY29sdW1ucyBieSAxMDAgdG8gY2xlYW4gdGhlbiBhbmQgcHV0IHRoZW0gYmV0d2VlbiAwIGFuZCAxDQogICAgICAgIG11dGF0ZV9hdCh2YXJzKHBlcmNlbnRfYW5hbGZhYmV0bywgcGVyY2VudF9zaW5fc2VydmljaW9fZWxlY3RyaWNvLCANCiAgICAgICAgICAgICAgICAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEsDQogICAgICAgICAgICAgICAgICAgICAgIHBlcmNlbnRfc2luX3NhbmVhbWllbnRvX21lam9yYWRvLA0KICAgICAgICAgICAgICAgICAgICAgICBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsIHBlcmNlbnRfdXJiYW5hLA0KICAgICAgICAgICAgICAgICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCksIH4oLiAvIDEwMCkpICU+JSANCiAgICAgICAgIyBtdXRhdGluZyBuZXcgY29sdW1ucyB3aXRoIHBvcHVsYXRpb25zDQogICAgICAgIG11dGF0ZShwb2JfYW5hbGZhYmV0byAgICAgICAgICAgICAgID0gcGVyY2VudF9hbmFsZmFiZXRvICogcG9ibGFjaW9uXzIwMTksDQogICAgICAgICAgICAgICBwb2Jfc2luX2FndWFfc2VndXJhICAgICAgICAgID0gcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKiBwb2JsYWNpb25fMjAxOSwgDQogICAgICAgICAgICAgICBwb2Jfc2luX3NlcnZpY2lvX2VsZWN0cmljbyAgID0gcGVyY2VudF9zaW5fc2VydmljaW9fZWxlY3RyaWNvICogcG9ibGFjaW9uXzIwMTksDQogICAgICAgICAgICAgICBwb2Jfc2luX3NhbmVhbWllbnRvX21lam9yYWRvID0gcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gKiBwb2JsYWNpb25fMjAxOSwNCiAgICAgICAgICAgICAgIHBvYl91cmJhbmEgICAgICAgICAgICAgICAgICAgPSBwZXJjZW50X3VyYmFuYSAqIHBvYmxhY2lvbl8yMDE5KSAlPiUgDQogICAgICAgIHNlbGVjdCgtYyhtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25faW5pY2lhbCwgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX3ByaW1hcmlhLCANCiAgICAgICAgICAgICAgIG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9tZWRpYSwgcG9ibGFjaW9uX3RvdGFsXzIwMTEsIGhvZ2FyZXNfMjAxMSwNCiAgICAgICAgICAgICAgIHBvYmxhY2lvbl9pbmZhbnRpbF9tZW5vcl9kZV8xMl9hbm9zLCBwb2JsYWNpb25fYWRvbGVzY2VudGVzX2RlXzEyX2FfMTdfYW5vcywgDQogICAgICAgICAgICAgICBwb2JsYWNpb25fZGVfMThfYW5vc195X21hcykpLA0KICAgICAgICAgICAgIGJ5ID0gInBjb2RlMyIpICU+JSANCiAgIyBtdXRhdGluZyBuZXcgdmFyaWFibGVzIGFuZCBtYWtpbmcgc3VyZSBOQXMgYmVjb21lIDBzIA0KICBtdXRhdGUoYmVuZWZpY2lhcmlvcyAgICAgICAgICA9IGlmZWxzZShpcy5uYShiZW5lZmljaWFyaW9zKSwgMCwgYmVuZWZpY2lhcmlvcyksDQogICAgICAgICBvcmdfY291bnQgICAgICAgICAgICAgID0gaWZlbHNlKGlzLm5hKG9yZ19jb3VudCksIDAsIG9yZ19jb3VudCksDQogICAgICAgICBlZHVjYWNpb25fYmVuICAgICAgICAgICAgID0gaWZlbHNlKGlzLm5hKGVkdWNhY2lvbl9iZW4pLCAwLCBlZHVjYWNpb25fYmVuKSwNCiAgICAgICAgIG51dHJpY2lvbl9iZW4gICAgICAgICAgICAgPSBpZmVsc2UoaXMubmEobnV0cmljaW9uX2JlbiksIDAsIG51dHJpY2lvbl9iZW4pLA0KICAgICAgICAgcHJvdGVjY2lvbkdCVl9iZW4gICAgICAgICA9IGlmZWxzZShpcy5uYShwcm90ZWNjaW9uR0JWX2JlbiksIDAsIHByb3RlY2Npb25HQlZfYmVuKSwNCiAgICAgICAgIHByb3RlY2Npb25HZW5lcmFsX2JlbiAgICAgPSBpZmVsc2UoaXMubmEocHJvdGVjY2lvbkdlbmVyYWxfYmVuKSwgMCwgcHJvdGVjY2lvbkdlbmVyYWxfYmVuKSwNCiAgICAgICAgIHByb3RlY2Npb25OTkFfYmVuICAgICAgICAgPSBpZmVsc2UoaXMubmEocHJvdGVjY2lvbk5OQV9iZW4pLCAwLCBwcm90ZWNjaW9uTk5BX2JlbiksDQogICAgICAgICBzYWx1ZF9iZW4gICAgICAgICAgICAgICAgID0gaWZlbHNlKGlzLm5hKHNhbHVkX2JlbiksIDAsIHNhbHVkX2JlbiksDQogICAgICAgICBzZWd1cmlkYWRfYWxpbWVudGFyaWFfYmVuID0gaWZlbHNlKGlzLm5hKHNlZ3VyaWRhZF9hbGltZW50YXJpYV9iZW4pLCAwLCBzZWd1cmlkYWRfYWxpbWVudGFyaWFfYmVuKSwNCiAgICAgICAgIHdhc2hfYmVuICAgICAgICAgICAgICAgICAgPSBpZmVsc2UoaXMubmEod2FzaF9iZW4pLCAwLCB3YXNoX2JlbiksDQogICAgICAgICBub3RfY292ZXJlZF9wb2JyZSAgICAgID0gcG9iX3BvYnJlIC0gYmVuZWZpY2lhcmlvcywNCiAgICAgICAgIGNvdmVyYWdlX3BlcmNlbnQgICAgICAgPSBiZW5lZmljaWFyaW9zIC8gcG9ibGFjaW9uXzIwMTksDQogICAgICAgICBjb3ZlcmFnZV9wb2JyZV9wZXJjZW50ID0gYmVuZWZpY2lhcmlvcyAvIHBvYl9wb2JyZSwNCiAgICAgICAgIHBlcmNlbnRfdG90YWxfYmVuICAgICAgPSBiZW5lZmljaWFyaW9zIC8gc3VtKGJlbmVmaWNpYXJpb3MpLA0KICAgICAgICAgb3JnX3ByZXNlbnQgICAgICAgICAgICA9IGlmZWxzZShiZW5lZmljaWFyaW9zID4gMCwgVFJVRSwgRkFMU0UpLA0KICAgICAgICAgcG9iX3BvYnJlX3Njb3JlICAgICA9IHJlc2NhbGUocG9iX3BvYnJlLCB0byA9IGMoMCwxKSksIA0KICAgICAgICAgcGVyY2VudF9wb2JyZV9zY29yZSA9IHJlc2NhbGUocGVyY2VudF9wb2JyZSwgdG8gPSBjKDAsMSkpLCANCiAgICAgICAgIHBvdmVydHlfc2NvcmUgICAgICAgPSAocG9iX3BvYnJlX3Njb3JlICsgcGVyY2VudF9wb2JyZV9zY29yZSkgLyAyKQ0KDQojIHRha2luZyBhIHN1YnNldCBvZiBwYXJyIHRvIG9ubHkgZ2V0IHBhcnJpc2hlcyB3aGVyZSB0aGUgbnVtYmVyIG9mIGJlbmVmaWNpYXJpZXMgZG9lcyBub3QgZXhjZWVkIHRoZSBudW1iZXIgb2YgcG9vciBwZXJzb25zDQpwYXJyMCA8LSBwYXJyICU+JSANCiAgZmlsdGVyKG5vdF9jb3ZlcmVkX3BvYnJlID49IDEpICU+JSANCiAgbXV0YXRlKGdhcF9zY29yZSA9IChyZXNjYWxlKG5vdF9jb3ZlcmVkX3BvYnJlLCB0byA9IGMoMCwxKSkgKyBwZXJjZW50X3BvYnJlX3Njb3JlKSAvIDIpDQoNCmBgYA0KDQpgYGB7ciB3cml0ZS1jc3YtcGFycjAsIGVjaG8gPSBGQUxTRSwgcmVzdWx0cyA9IEZBTFNFfQ0KIyBldmFsbGVkIG91dCAtLSBjaGFuZ2UgdGhpcyBpZiB5b3Ugd2FudCB0aGUgY3N2IGZvciB0YWJsZWF1IG9yIHdoYXRldmVyDQp3cml0ZV9jc3YocGFycjAsICJwYXJyMC5jc3YiKQ0KYGBgDQoNCiMjIFN1bW1hcnkgb2YgY292ZXJhZ2UgYW5kIGdhcHMNCg0KPiBBcyBhIHByZWxpbWluYXJ5IGFuYWx5c2lzLCBhbGwgYHIgbnJvdyhwYXJyKWAgcGFycmlzaGVzIGhhdmUgYmVlbiBzcGxpdCBpbnRvIHRocmVlIGdyb3VwcyAtLSBfb3Zlcl8sIHdoZXJlIHRoZSBudW1iZXIgb2YgdW5pcXVlIGJlbmVmaWNpYXJpZXMgcmVhY2hlZCBleGNlZWRzIHRoZSBudW1iZXIgb2YgcG9vciBwZXJzb25zIGluIHRoYXQgcGFycmlzaDsgX3VuZGVyXywgd2hlcmUgdGhlIGNvdmVyYWdlIGlzIGxlc3MgdGhhbiB0aGUgbnVtYmVyIG9mIHBvb3IgcGVyc29uczsgYW5kIF9ub3QgcmVhY2hlZF8sIHdoZXJlIG5vIGFjdGl2aXRpZXMgaGF2ZSBvY2N1cnJlZC4gSG93ZXZlciwgaXQgc2hvdWxkIGJlIG5vdGVkIHRoYXQgYSB0b3RhbCBvZiAqKmByIHJvdW5kKGZpbHRlcihwYXJyLCBiZW5lZmljaWFyaW9zID09IDApICU+JSB7c3VtKC4kcG9iX3BvYnJlKX0sIGRpZ2l0cyA9IDApYCoqIHBvb3IgcGVyc29ucyByZXNpZGUgaW4gdGhlICoqYHIgbnJvdyhwYXJyW3BhcnIkYmVuZWZpY2lhcmlvcyA9PSAwLF0pYCoqIHBhcnJpc2hlcyB0aGF0IGhhdmUgbm90IGJlZW4gcmVhY2hlZCwgdGhpcyBpcyBvbmx5ICoqYHIgcm91bmQoZmlsdGVyKHBhcnIsIGJlbmVmaWNpYXJpb3MgPT0gMCkgJT4lIHtzdW0oLiRwb2JfcG9icmUpfSAvIHN1bShwYXJyJG5vdF9jb3ZlcmVkX3BvYnJlKSAqMTAwLCBkaWdpdHMgPSAwKWAlKiogb2YgdGhlICoqYHIgcm91bmQoc3VtKHBhcnIkbm90X2NvdmVyZWRfcG9icmUpLCBkaWdpdHMgPSAwKWAqKiBwb29yIHBlcnNvbnMgbm90IGNvdmVyZWQgYnkgcmVzcG9uc2UgYWN0aXZpdGllcy4gVGhpcyBpbmRpY2F0ZXMgdGhhdCAxKSB0aGVyZSBpcyBtdWNoIHJvb20gdG8gZXhwYW5kIGluIHRoZSBwYXJyaXNoZXMgd2hlcmUgd2UgYXJlIGFscmVhZHkgcHJlc2VudCBhbmQgMikgc3BhcmVseSBwb3B1bGF0ZWQsIHJlbW90ZSBhbmQsIGNvbnNlcXVlbnRseSwgcG9vcmVyIHBhcnJpc2hlcyBoYXZlLCBzbyBmYXIsIGJlZW4gbGVmdCBvdXQgb2YgdGhlIHJlc3BvbnNlLiANCg0KDQpgYGB7cn0NCnBhcnIgJT4lIA0KICBtdXRhdGUoY292ZXJhZ2VfdHlwZSA9IGNhc2Vfd2hlbihub3RfY292ZXJlZF9wb2JyZSA8PSAwIH4gIm92ZXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3RfY292ZXJlZF9wb2JyZSA+IDAgJiBiZW5lZmljaWFyaW9zID49IDEgfiAidW5kZXIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuZWZpY2lhcmlvcyA9PSAwIH4gIm5vdF9yZWFjaGVkIikpICU+JSANCiAgZ3JvdXBfYnkoY292ZXJhZ2VfdHlwZSkgJT4lIA0KICBzdW1tYXJpc2UocGFycm9xdWlhcyA9IG4oKSwNCiAgICAgICAgICAgIGJlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcyksDQogICAgICAgICAgICBub3RfY292ZXJlZF9wb2JyZSA9IHN1bShub3RfY292ZXJlZF9wb2JyZSksIA0KICAgICAgICAgICAgYXZnX29yZ19jb3VudCA9IG1lYW4ob3JnX2NvdW50KSwNCiAgICAgICAgICAgIHBlcmNlbnRfcG9icmUgPSAoc3VtKHBvYl9wb2JyZSkpIC8gKHN1bShwb2JsYWNpb25fMjAxOSkpLA0KICAgICAgICAgICAgcGVyY2VudF91cmJhbmEgPSAoc3VtKHBvYl91cmJhbmEpKSAvIChzdW0ocG9ibGFjaW9uXzIwMTkpKSwNCiAgICAgICAgICAgIHBlcmNlbnRfc2luX2FndWFfc2VndXJhID0gKHN1bShwb2Jfc2luX2FndWFfc2VndXJhKSkgLyAoc3VtKHBvYmxhY2lvbl8yMDE5KSksDQogICAgICAgICAgICBwZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbyA9IChzdW0ocG9iX3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbykpIC8NCiAgICAgICAgICAgICAgKHN1bShwb2JsYWNpb25fMjAxOSkpKSAlPiUgDQogIGdhdGhlcihrZXkgPSB2YXJpYWJsZSwgdmFsdWUgPSB2YWx1ZSwgMjpuY29sKC4pKSAlPiUgDQogIHNwcmVhZF8oa2V5ID0gbmFtZXMoLilbMV0sIHZhbHVlID0gJ3ZhbHVlJykgJT4lIA0KICByZWxvY2F0ZShub3RfcmVhY2hlZCwgLmFmdGVyID0gdW5kZXIpICU+JSANCiAgcGFuZGVyKGJpZy5tYXJrID0gIiwiKQ0KICANCmBgYA0KDQo+IFdlIG5vdGUgdGhhdCB0aGUgKipgciBucm93KHBhcnJbcGFyciRub3RfY292ZXJlZF9wb2JyZSA8PSAwLF0pYCoqIHBhcnJpc2hlcyBpbiB0aGUgX292ZXJfIGNhdGVnb3J5IGFyZSBtdWNoIGxlc3MgcG9vciBhbmQgbXVjaCBtb3JlIHVyYmFuIGRlc3BpdGUgaGF2aW5nICoqYHIgcm91bmQoZmlsdGVyKHBhcnIsIG5vdF9jb3ZlcmVkX3BvYnJlIDw9IDApICU+JSB7c3VtKC4kYmVuZWZpY2lhcmlvcyl9IC8gc3VtKHBhcnIkYmVuZWZpY2lhcmlvcykgKiAxMDAsIGRpZ2l0cyA9IDApYCUqKiBvZiBhbGwgYmVuZWZpY2lhcmllcy4gVGhlc2UgcGFycmlzaGVzIGFyZSBzaG93biBpbiB0aGUgdGFibGUgYmVsb3cuIA0KDQojIyMgVG9wIHBhcnJpc2hlcyBpbiB0ZXJtcyBvZiBjb3ZlcmFnZQ0KDQpgYGB7cn0NCnBhcnIgJT4lIA0KICBtdXRhdGUoY292ZXJhZ2VfdHlwZSA9IGNhc2Vfd2hlbihub3RfY292ZXJlZF9wb2JyZSA8PSAwIH4gIm92ZXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3RfY292ZXJlZF9wb2JyZSA+IDAgJiBiZW5lZmljaWFyaW9zID49IDEgfiAidW5kZXIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuZWZpY2lhcmlvcyA9PSAwIH4gIm5vdF9yZWFjaGVkIikpICU+JSAgDQogIGZpbHRlcihjb3ZlcmFnZV90eXBlID09ICJvdmVyIikgJT4lIA0KICBzZWxlY3QoZXN0YWRvLCBtdW5pY2lwaW8sIGVzdGFkbywgcGFycm9xdWlhLCBiZW5lZmljaWFyaW9zLCBwb2JfcG9icmUpICU+JQ0KICBtdXRhdGUoY292ZXJhZ2VfcG9vciA9IGJlbmVmaWNpYXJpb3MgLyBwb2JfcG9icmUgKiAxMDApICU+JSANCiAgYXJyYW5nZShkZXNjKGJlbmVmaWNpYXJpb3MpKSAlPiUgDQogIHBhbmRlcihiaWcubWFyayA9ICIsIikNCmBgYA0KDQoNCj4gVGhlc2UgKipgciBucm93KHBhcnJbcGFyciRub3RfY292ZXJlZF9wb2JyZSA8PSAwLF0pYCoqIHBhcnJpc2hlcyB3aWxsIGxhcmdlbHkgYmUgZXhjbHVkZWQgaW4gdGhlIGFuYWx5c2lzIGluIHRoZSByZW1haW5kZXIgb2YgdGhpcyByZXBvcnQgYXMgaXQgaXMgY2xlYXIgdGhhdCBubyBmdXJ0aGVyIHJlc291cmNlcyBzaG91bGQgYmUgYWxsb2NhdGVkIHRvIHRoZW0uIA0KDQo+IFRob3VnaCBpdCBzaG91bGQgYmUgbWVudGlvbmVkIHRoYXQgaXQgaXMgbGlrZWx5IHRoYXQgcGFydG5lcnMgaGF2ZSByZXBvcnRlZCBhY3Rpdml0aWVzIHdoaWNoIG9jY3VycmVkIGluIG90aGVyIHBhcnRzIG9mIHRoZSBjYXBpdGFsIGluIEFsdGFncmFjaWEsIGFzIHRoZSB0b3RhbCBudW1iZXIgb2YgYmVuZWZpZmljYXJpZXMgcmVhY2hlZCBpbiB0aGUgd2hvbGUgb2YgRGlzdHJpdG8gQ2FwaXRhbCBpcyBvbmx5IGByIHN1bW1hcmlzZShwYXJyLCBiZW5lZmljaWFyaW9zID0gc3VtKGJlbmVmaWNpYXJpb3NbbXVuaWNpcGlvID09ICJMSUJFUlRBRE9SIl0pKWAuIFRoaXMgYW5hbHlzaXMgd2lsbCBiZSBjb3JyZWN0ZWQgaWYgdXBkYXRlZCBpbmZvcm1hdGlvbiBpcyByZWNlaXZlZC4gDQoNCg0KIyMgR2VvZ3JhcGhpY2FsIGFuYWx5c2lzIG9mIEdhcHMNCg0KIyMjIEJhcnBsb3Qgb2YgY292ZXJhZ2UgYW5kIGdhcHMgYnkgc3RhdGUNCl9tb3VzZSBvdmVyIHBsb3QgZm9yIG1vcmUgZGV0YWlsc18NCg0KYGBge3IgcGFycjAtc3RhdGUtUExPVH0NCiMgcmVmIGZvciBwcmludG5nIHN0YXRlX29yZC4gSSdtIHJlYWxseSBub3Qgc3VyZSBob3cgdG8gZXh0cmFjdCBhbGwgdGhlIHZhcmlhYmxlcyBhcyBhIGxpc3QNCiMgcGFycjAgJT4lIA0KIyAgIGdyb3VwX2J5KGVzdGFkbykgJT4lIA0KIyAgIHN1bW1hcmlzZShub3RfY292ZXJlZF9wb2JyZSA9IHN1bShub3RfY292ZXJlZF9wb2JyZSkpICU+JSANCiMgICBhcnJhbmdlKGRlc2Mobm90X2NvdmVyZWRfcG9icmUpKSAlPiUgDQojICAgc2VsZWN0KGVzdGFkbykgJT4lIGFzLmxpc3QoYXMuZGF0YS5mcmFtZSh0KC4pKSkNCg0Kc3RhdGVfb3JkIDwtIGMoIlpVTElBIiwgIkxBUkEiLCAiQ0FSQUJPQk8iLCAiTUlSQU5EQSIsICJBTlpPQVRFR1VJIiwgIkFSQUdVQSIsICJCT0xJVkFSIiwNCiAgICAgICAgICAgICAgICJQT1JUVUdVRVNBIiwgIlNVQ1JFIiwgIkdVQVJJQ08iLCAiRkFMQ09OIiwgIk1PTkFHQVMiLCAiQkFSSU5BUyIsICJNRVJJREEiLA0KICAgICAgICAgICAgICAgIlRBQ0hJUkEiLCAiVFJVSklMTE8iLCAiWUFSQUNVWSIsICJBUFVSRSIsICJESVNUUklUTyBDQVBJVEFMIiwgIk5VRVZBIEVTUEFSVEEiLA0KICAgICAgICAgICAgICAgIkNPSkVERVMiLCAiVkFSR0FTIiwgIkRFTFRBIEFNQUNVUk8iLCAiQU1BWk9OQVMiKQ0KICANCnN0YWNrX3RleHQgPC0gcGFycjAgJT4lIA0KICBncm91cF9ieShlc3RhZG8pICU+JSANCiAgc3VtbWFyaXNlKGJlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcyksDQogICAgICAgICAgICB0b3RhbCA9IHN1bShwb2JfcG9icmUpKSAlPiUgDQogIG11dGF0ZShwZXJjZW50X3JlYWNoZWQgPSByb3VuZChiZW5lZmljaWFyaW9zIC8gdG90YWwgKiAxMDAsIGRpZ2l0cyA9IDIpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyh0b3RhbCkpIA0KDQpzdGF0ZV9zdGFjayA8LSBwYXJyMCAlPiUgDQogIHNlbGVjdChlc3RhZG8sIGJlbmVmaWNpYXJpb3MsIG5vdF9jb3ZlcmVkX3BvYnJlKSAlPiUgDQogIGdyb3VwX2J5KGVzdGFkbykgJT4lDQogIHN1bW1hcmlzZShiZW5lZmljaWFyaW9zID0gc3VtKGJlbmVmaWNpYXJpb3MpLCANCiAgICAgICAgICAgIG5vdF9jb3ZlcmVkX3BvYnJlID0gc3VtKG5vdF9jb3ZlcmVkX3BvYnJlKSkgJT4lIA0KICBwaXZvdF9sb25nZXIoYyhiZW5lZmljaWFyaW9zLG5vdF9jb3ZlcmVkX3BvYnJlKSwNCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBvYl90eXBlIiwgdmFsdWVzX3RvID0gInRvdGFsIikgJT4lIA0KICANCiAgZ2dwbG90KGFlcyh4ID0gZXN0YWRvLCB5ID0gdG90YWwpKSArDQogIGdlb21fY29sKGFlcyhmaWxsID0gcG9iX3R5cGUpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbCA9IGNvbW1hKSArDQogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gc3RhdGVfb3JkKSArDQogIGdlb21fdGV4dChkYXRhID0gc3RhY2tfdGV4dCwgYWVzKHkgPSAyMDAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwZXJjZW50X3JlYWNoZWQpLCBzaXplID0gMikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA1KSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSArDQogIHhsYWIoIiIpICsgeWxhYigiUG9vciBwZXJzb25zIikgKyBsYWJzKGZpbGwgPSAiIikNCg0KZ2dwbG90bHkoc3RhdGVfc3RhY2spICU+JSANCiAgbGF5b3V0KGxlZ2VuZCA9IGxpc3QoZm9udCA9IGxpc3Qoc2l6ZSA9IDYpKSkgJT4lIA0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCg0KYGBgDQoNCj4gVGhlIHN0YXRlcyB3aXRoIHRoZSBoaWdoZXN0IHBlcmNlbnRhZ2VzIChsaXN0ZWQgYXQgdGhlIGJvdHRvbSBvZiBlYWNoIGJhcikgYXJlIERpc3RyaXRvIENhcGl0YWwsIFRhY2hpcmEsIEJvbGl2YXIsIERlbHRhIEFtYWN1cm8sIE1pcmFuZGEgYW5kIFp1bGlhLiBDYXJhYm9ibyBoYXMgdGhlIGxvd2VzdCBwZXJjZW50YWdlIG9mIGl0cyBwb29yIHBvcHVsYXRpb24gY292ZXJlZC4gT24gYXZlcmFnZSwgYWZ0ZXIgdGhlIGV4Y2x1c2lvbiBvZiB0aGUgdG9wIGByIG5yb3cocGFycltwYXJyJG5vdF9jb3ZlcmVkX3BvYnJlIDw9IDAsXSlgIHBhcnJpc2hlcywgKipgciByb3VuZChzdW0ocGFyciRiZW5lZmljaWFyaW9zKSAvIHN1bShwYXJyJHBvYl9wb2JyZSkgKiAxMDAsIGRpZ2l0cyA9IDEpYCUqKiBvZiBwb29yIHBlcnNvbnMgaGF2ZSBiZWVuIHJlYWNoZWQuIA0KDQo+IExldCB1cyBub3cgbW92ZSBkb3duIHRvIGEgbG93ZXIgbGV2ZWwgb2YgZ3JhbnVsYXJpdHkgYXMgc3RhdGUtbGV2ZWwgYW5hbHlzaXMgaXMgc3RpbCBxdWl0ZSBzdXBlcmZpY2lhbDogDQoNCg0KIyMjIFNjYXR0ZXJwbG90IG9mIGdhcHMgYnkgcGFycmlzaCANCg0KDQpgYGB7ciBwYXJycGxvdC1QTE9UTFl9DQoNCnBhcnJwbG90IDwtIHBhcnIwICU+JSANCiAgbXV0YXRlX2F0KHZhcnMocG9iX3BvYnJlLCBub3RfY292ZXJlZF9wb2JyZSwgb3JnX2NvdW50KSwgfihyb3VuZCguKSkpICU+JSANCiAgbXV0YXRlKHBlcmNlbnRfcG9icmUgPSByb3VuZChwZXJjZW50X3BvYnJlLCBkaWdpdHMgPSAyKSklPiUgDQogIGdncGxvdChhZXMoeCA9IG5vdF9jb3ZlcmVkX3BvYnJlLCB5ID0gcGVyY2VudF9wb2JyZSwgDQogICAgICAgICAgICAgY29sb3VyID0gb3JnX2NvdW50LCANCiAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUwKHBhcnJvcXVpYSwgIiwgIiwgZXN0YWRvKSkpICsNCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IG5vdF9jb3ZlcmVkX3BvYnJlKSwgYWxwaGEgPSAwLjc1KSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oDQogICAgY29sb3VycyA9IGMoImNvcm5mbG93ZXJibHVlIiwgInRvbWF0byIsICJmaXJlYnJpY2siKSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBsYWJlbHMgPSBjb21tYSkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygwLjMsIDUpKSArDQogIHhsYWIoIk5vdCBjb3ZlcmVkIHBvb3IiKSArIHlsYWIoIlBvdmVydHkgaW5jaWRlbmNlIikgKw0KICBsYWJzKGNvbG91ciA9ICJOdW1iZXIgb2YgXG5vcmdhbmlzYXRpb25zIikgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLA0KICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpDQoNCmdncGxvdGx5KHBhcnJwbG90LCB0b29sdGlwID0gYygieSIsICJ4IiwgInNpemUiLCAidGV4dCIsICJjb2xvdXIiKSkgJT4lIA0KICAgICAgICAgICBsYXlvdXQoc2hvd2xlZ2VuZCA9IFRSVUUsIGxlZ2VuZCA9IGxpc3QoZm9udCA9IGxpc3Qoc2l6ZSA9IDcpKSkgJT4lIA0KICAgICAgICAgICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCg0KYGBgDQpfeC1heGlzOiBudW1iZXIgb2YgcG9vciBwZXJzb25zOyB5LWF4aXM6IHBvdmVydHkgaW5jaWRlbmNlOyBzaXplOiBudW1iZXIgb2YgcG9vciBwZXJzb25zIG5vdCBjb3ZlcmVkOyBjb2xvdXI6IG51bWJlciBvZiBvcmdhbmlzYXRpb25zIHByZXNlbnRfDQpfbW91c2Ugb3ZlciBmb3IgZGV0YWlsc18NCg0KPiBIb3dldmVyLCBmcm9tIHRoZSBzY2F0dGVycGxvdCBhYm92ZSAtLSB3aGVyZSBlYWNoIHBvaW50IGlzIGEgcGFycmlzaCBhbmQgdGhlIHNpemUgc2hvd3MgdGhlIG51bWJlciBvZiBwb29yIHBlcnNvbnMgbm90IGNvdmVyZWQgKG5vdCBjb3ZlcmVkKSAtLSB3ZSBzZWUgdGhhdCB0aGVyZSBpcyBncmVhdCB2YXJpYXRpb24gaW4gdGhlIG51bWJlciBvZiB0aG9zZSBub3QgY292ZXJlZCBhcyB3ZWxsIGFzIGhvdyBjb25jZW50cmF0ZWQgdGhleSBhcmUgaW4gYSBnaXZlbiBwYXJyaXNoIChwb3ZlcnR5IGluY2lkZW5jZSk7IGJvdGggdGhlc2UgZmFjdG9ycyB3ZWlnaCBoZWF2aWx5IGluIHByb2dyYW1taW5nIHN0cmF0ZWdpZXMgYXMgd2VsbCBhcyBpbiB0aGUgZWFzZSBvZiBiZW5lZmljaWFyeSBzZWxlY3Rpb24uICANCg0KPiBCdXQgd2UgY2FuLCBhdCBsZWFzdCwgb2JzZXJ2ZSB0aGF0IHRoZSBwYXJyaXNoZXMgd2l0aCB0aGUgZ3JlYXRlc3QgbnVtYmVycyBvZiBub3QgY292ZXJlZCAoZm91bmQgYXQgX3Bvb3IgcGVyc29uczpfIDEwLDAwMC0xMDAsMDAwOyBfcG92ZXJ0eSBpbmNpZGVuY2U6XyAwLjI1LTAuNTApIGhhdmUgYSBtdWNoIGhpZ2hlciB0aGFuIGF2ZXJhZ2UgbnVtYmVyIG9mIG9yZ2FuaXNhdGlvbnMgcHJlc2VudC4gVGhpcyBtZWFucyB0aGF0IG9wZXJhdGlvbmFsIGJhcnJpZXJzIGFyZSBtdWNoIGxvd2VyIGluIGFjY2Vzc2luZyB0aGVzZSBwb3B1bGF0aW9ucyB0aGFuIHRoZSBwYXJyaXNoZXMgaW4gbGlnaHQgYmx1ZSBmb3VuZCBpbiB0aGUgbWlkZGxlIG9mIHRoZSBwbG90LiANCg0KPiBGb3IgYSBtb3JlIGRldGFpbGVkIHBsb3QsIHdpdGggc3RhdGUgZmlsdGVycywgcGxlYXNlIHZpc2l0IHRoaXMgbGluazogDQoNCiMjIyBTY2F0dGVycGxvdCBvZiBjb3ZlcmFnZSBhbmQgZ2FwcyBpbiBtdWx0aS1zZWN0b3IgcHJvZ3JhbW1pbmcNCg0KYGBge3J9DQoNCnNlY3Rvcl9wbG90IDwtIHBhcnIwICU+JSANCiAgbXV0YXRlKHByb3RlY2Npb25fYmVuID0gcm93U3VtcyguWzU6N10pKSAlPiUgDQogIHNlbGVjdCgtYyhwcm90ZWNjaW9uR0JWX2JlbiwgcHJvdGVjY2lvbkdlbmVyYWxfYmVuLCBwcm90ZWNjaW9uTk5BX2JlbiwgcGVyY2VudF90b3RhbF9iZW4sIHNlZ3VyaWRhZF9hbGltZW50YXJpYV9iZW4pKSAlPiUgDQogIG11dGF0ZShzZWN0b3JfY291bnQgPSByb3dTdW1zKHNlbGVjdCguLCBlbmRzX3dpdGgoIl9iZW4iKSkhPTApKSAlPiUgDQogIG11dGF0ZV9hdCh2YXJzKHBvYl9wb2JyZSwgbm90X2NvdmVyZWRfcG9icmUsIG9yZ19jb3VudCksIH4ocm91bmQoLikpKSAlPiUgDQogIG11dGF0ZShwZXJjZW50X3BvYnJlID0gcm91bmQocGVyY2VudF9wb2JyZSwgZGlnaXRzID0gMikpJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBub3RfY292ZXJlZF9wb2JyZSwgeSA9IHBlcmNlbnRfcG9icmUsIA0KICAgICAgICAgICAgIHRleHQgPSBwYXN0ZTAocGFycm9xdWlhLCAiLCAiLCBlc3RhZG8pLCANCiAgICAgICAgICAgICBzaXplID0gbm90X2NvdmVyZWRfcG9icmUpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNlY3Rvcl9jb3VudCksIGFscGhhID0gMC43NSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBsYWJlbHMgPSBjb21tYSkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygwLjMsIDUpKSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oDQogICAgY29sb3VycyA9IGMoImNvcm5mbG93ZXJibHVlIiwgIm1lZGl1bXB1cnBsZSIsICJmaXJlYnJpY2siKSkgKw0KICB4bGFiKCJOb3QgY292ZXJlZCBwb29yIikgKyB5bGFiKCJQb3ZlcnR5IGluY2lkZW5jZSIpICsNCiAgbGFicyhjb2xvdXIgPSAiTnVtYmVyIG9mIFxuc2VjdG9ycyIsIHNpemUgPSAiIikgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLA0KICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpDQoNCmdncGxvdGx5KHNlY3Rvcl9wbG90LCB0b29sdGlwID0gYygieSIsICJ4IiwgInRleHQiLCAiY29sb3VyIikpICU+JSANCiAgbGF5b3V0KHNob3dsZWdlbmQgPSBUUlVFLCBsZWdlbmQgPSBsaXN0KGZvbnQgPSBsaXN0KHNpemUgPSA3KSkpICU+JQ0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCiAgDQoNCg0KYGBgDQpfeC1heGlzOiBudW1iZXIgb2YgcG9vciBwZXJzb25zOyB5LWF4aXM6IHBvdmVydHkgaW5jaWRlbmNlOyBzaXplOiBudW1iZXIgb2YgcG9vciBwZXJzb25zIG5vdCBjb3ZlcmVkOyBjb2xvdXI6IG51bWJlciBvZiBzZWN0b3JzXw0KX21vdXNlIG92ZXIgZm9yIGRldGFpbHNfDQoNCiMjIFJlZmVyZW5jZSBUYWJsZSANCg0KPiBNb3ZlIHRoaXMgcmVmZXJlbmNlIHRhYmxlIHRvIHRoZSBiYWNrIA0KDQoNCmBgYHtyfQ0KcGFycjAgJT4lIA0KICBtdXRhdGUocHJvdGVjY2lvbl9iZW4gPSByb3dTdW1zKC5bNTo3XSkpICU+JSANCiAgc2VsZWN0KC1jKHByb3RlY2Npb25HQlZfYmVuLCBwcm90ZWNjaW9uR2VuZXJhbF9iZW4sIHByb3RlY2Npb25OTkFfYmVuLCBwZXJjZW50X3RvdGFsX2Jlbiwgc2VndXJpZGFkX2FsaW1lbnRhcmlhX2JlbikpICU+JSANCiAgbXV0YXRlKHNlY3Rvcl9jb3VudCA9IHJvd1N1bXMoc2VsZWN0KC4sIGVuZHNfd2l0aCgiX2JlbiIpKSE9MCkpICU+JSANCiAgbXV0YXRlX2F0KHZhcnMocG9iX3BvYnJlLCBub3RfY292ZXJlZF9wb2JyZSwgb3JnX2NvdW50KSwgfihyb3VuZCguKSkpICU+JSANCiAgbXV0YXRlKHBlcmNlbnRfcG9icmUgPSByb3VuZChwZXJjZW50X3BvYnJlLCBkaWdpdHMgPSAyKSkgJT4lIA0KICBzZWxlY3QoZXN0YWRvLCBtdW5pY2lwaW8sIHBhcnJvcXVpYSwgcGNvZGUzLCBvcmdfY291bnQsIHNlY3Rvcl9jb3VudCwgDQogICAgICAgICBwZXJjZW50X3BvYnJlLCBwZXJjZW50X3VyYmFuYSwgbm90X2NvdmVyZWRfcG9icmUsDQogICAgICAgICBiZW5lZmljaWFyaW9zLCBlZHVjYWNpb25fYmVuLCBudXRyaWNpb25fYmVuLCBwcm90ZWNjaW9uX2Jlbiwgc2FsdWRfYmVuLCB3YXNoX2JlbikgJT4lIA0KICBhcnJhbmdlKGRlc2Mobm90X2NvdmVyZWRfcG9icmUpKSAlPiUgDQogIGRhdGF0YWJsZShmaWx0ZXIgPSAidG9wIiwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLCBzY3JvbGxYID0gVFJVRSkpICU+JSANCiAgRFQ6OmZvcm1hdFN0eWxlKGNvbHVtbnMgPSBjb2xuYW1lcyguKSwgZm9udHNpemUgPSAiMTJwdCIpDQoNCmBgYA0KDQoNCg0KDQojIyBEZWNpc2lvbiB0cmVlcw0KDQo+IFRocmVlIHRyZWVzIGhhdmUgYmVlbiBidWlsdCB0byBzcGxpdCBwYXJyb3F1aWFzIHVwIGludG8gdGFyZ2V0dGluZyBncm91cHMgYmFzZWQgb24gdGhlaXIgDQpjaGFyYWN0ZXJpc3RpY3MuIFRoZSB2YXJpYWJsZXMgc2VsZWN0ZWQgbGFyZ2VseSBvcmlnaW5hdGUgZnJvbSB0aGUgY2Vuc3VzIGRhdGFzZXQsIHdpdGggc29tZSBoYXZpbmcgYmVlbiB1cGdyYWRlZCBieSB0aGUgMjAxOSBNdW5pY2lwYWwgUHJpb3JpdGlzYXRpb24gVG9vbCwgd2hpY2ggd2FzIGEgUHJpbmNpcGFsIENvbXBvbmVudHMgQW5hbHlzaXMgb2Yga2V5IHZhcmlhYmxlcyByZWxhdGVkIHRvIHBvdmVydHksIGhlYWx0aCBhbmQgbW9ydGFsaXR5IGFuZCB2aW9sZW5jZSBhbmQgaW5zZWN1cml0eS4gDQoNCj4gUGFycmlzaGVzIHdlcmUgc3BsaXQgaW50byBncm91cHMgYmFzZWQgb24gdGhlaXIgdmFyaW91cyBjaGFyYWN0ZXJpc3RpY3M7IHRoZSB0aHJlZSB0cmVlcyBkZXZlbG9wZWQgd2VyZSB1c2VkIHRvIHNwbGl0IHBhcnJpc2hlcyBpbnRvIGdyb3VwcyBiYXNlZCBvbjogDQoNCiAgMS4gVGhlIG51bWJlciBvZiBwb29yIHBlcnNvbnMgbm90IGNvdmVyZWQgYnkgaHVtYW5pdGFyaWFuIHBhcnRuZXJzOw0KICAyLiBXaGV0aGVyIG9yIG5vdCBodW1hbml0YXJpYW4gcGFydG5lcnMgd2VyZSBwcmVzZW50IC0tIHRoaXMgd2FzIHRvIHVuZGVyc3RhbmQgdGhlIGJpYXNlcyBhbmQgZGlzcG9zaXRpb25zIHBhcnRuZXJzIGhhZCBpbiBzZWxlY3Rpbmcgd2hlcmUgdG8gd29yazsgYW5kIA0KICAzLiBUaGUgcG92ZXJ0eSBzY29yZSwgd2hpY2ggaXMganVzdCBhIHJlc2NhbGVkIGF2ZXJhZ2Ugb2YgdGhlIG51bWJlciBvZiBwb29yIHBlcnNvbnMgYW5kIHRoZSBwb3ZlcnR5IGluY2lkZW5jZSBvZiBlYWNoIHBhcnJpc2guIA0KICANCj4gVGhlIHNwZWNpZmljIHZhcmlhYmxlcyBhbmQgZm9ybXVsYWUgdXNlZCBmb3IgZWFjaCBvZiB0aGUgdHJlZXMgY2FuIGJlIHNlZW4gYnkgdW5oaWRpbmcgdGhlIHNvdXJjZSBjb2RlIGluIHRoZSBjaHVuayBiZWxvdy4gDQoNCmBgYHtyIHRyZWVzLVJFRn0NCiANCiMgd2UgbWF5IGZpdCBuZXcgdHJlZXMgaW4gdGhlIGZ1dHVyZSBhcyBtb3JlIGRhdGEgY29tZXMgaW4gYW5kIHRlc3QgZXhpc3Rpbmcgb25lcyB3aXRoIG5ldyBkYXRhLiBUaGV5IGFyZW4ndCByZWFsbHkgbWVhbnQgdG8gYmUgcHJlZGljdGl2ZSBhbmQgbW9yZSB0byBvcmdhbmlzZSBhIHJlc3BvbnNlIC0tIHdlJ3JlIG5vdCByZWFsbHkgdXNpbmcgdGhlbSB0byB0cmFpbiBhIG1vZGVsLiBUcmVlMiwgaW4gcGFydGljdWxhciBpcyB2ZXJ5IGJhY2t3YXJkLWxvb2tpbmcsIHRob3VnaCBpdCB3b3VsZCBiZSBpbnRlcmVzdGluZyB0byBzZWUgaG93IHdlbGwgaXQgaG9sZHMgdXAgb3ZlciB0aW1lLiBIb3BlZnVsbHkgaXQncyBub3QgdmVyeSBwcmVkaWN0aXZlLiANCg0Kc2V0LnNlZWQoMzAwMCkNCg0KDQojIG51bWJlciBvZiBub3QgY292ZXJlZCBwb29yIHBlcnNvbnMgDQp0cmVlMSA8LSBwYXJyMCAlPiUNCiAgcnBhcnQobm90X2NvdmVyZWRfcG9icmUgfiBlc3RhZG8gKyBwZXJjZW50X3BvYnJlICsgcGVyY2VudF91cmJhbmEgKyANCiAgICAgICAgZGVuc2lkYWRfcHBsX2ttMiArIHJhem9uX2RlX2RlcGVuZGVuY2lhX2RlX21lbm9yZXNfZGVfMTVfYW5vcyArIA0KICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCArICANCiAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKyBwZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbyArDQogICAgICAgIHBlcmNlbnRfc2luX3NlcnZpY2lvX2VsZWN0cmljbyArIHBlcmNlbnRfYW5hbGZhYmV0byArIHBlcmNlbnRfaG9nYXJlc19qZWZhdHVyYV9mZW1lbmluYSwgDQogICAgICAgIHByb21lZGlvX2RlX3BlcnNvbmFzX3Bvcl92aXZpZW5kYSwgZGF0YSA9IC4sIGNwID0gMC4wMzgpDQoNCiMgaW50ZXJlc3RlZCBhZ2FpbiAtLSBqdXN0IHRvIHNob3cgdGhlIGRlY2lzaW9uIHRyZWUgb2YgaG93IHBhcnRuZXJzIHNlZW0gdG8gaGF2ZSBjaG9zZW4gbG9jYXRpb25zLiAjIHVzaW5nIGZ1bGwgcGFyciBkYXRhc2V0IGZvciB0aGUgdHJlZQ0KdHJlZTIgPC0gcGFyciAlPiUgDQogIHJwYXJ0KG9yZ19wcmVzZW50IH4gcGVyY2VudF9wb2JyZSArIHBlcmNlbnRfdXJiYW5hICsgZGVuc2lkYWRfcHBsX2ttMiArIA0KICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV9kZV9tZW5vcmVzX2RlXzE1X2Fub3MgKyByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCArICANCiAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKyBwZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbyArDQogICAgICAgIHBlcmNlbnRfc2luX3NlcnZpY2lvX2VsZWN0cmljbyArIHBlcmNlbnRfYW5hbGZhYmV0byArIHBlcmNlbnRfaG9nYXJlc19qZWZhdHVyYV9mZW1lbmluYSwgDQogICAgICAgIHByb21lZGlvX2RlX3BlcnNvbmFzX3Bvcl92aXZpZW5kYSwgZGF0YSA9IC4sIG1pbmJ1Y2tldCA9IDEwMCkNCg0KIyB0cmVlIGJhc2VkIG9uIHBvdmVydHlfc2NvcmUNCnRyZWUzIDwtIHBhcnIwICU+JQ0KICBycGFydChwb3ZlcnR5X3Njb3JlIH4gZXN0YWRvICsgcGVyY2VudF91cmJhbmEgKyBkZW5zaWRhZF9wcGxfa20yICsNCiAgICAgICAgcmF6b25fZGVfZGVwZW5kZW5jaWFfZGVfbWVub3Jlc19kZV8xNV9hbm9zICsgcmF6b25fZGVfZGVwZW5kZW5jaWFfdG90YWwgKyAgDQogICAgICAgIHBlcmNlbnRfc2luX2FndWFfc2VndXJhICsgcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gKw0KICAgICAgICBwZXJjZW50X3Npbl9zZXJ2aWNpb19lbGVjdHJpY28gKyBwZXJjZW50X2FuYWxmYWJldG8gKyBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsDQogICAgICAgIHByb21lZGlvX2RlX3BlcnNvbmFzX3Bvcl92aXZpZW5kYSwgZGF0YSA9IC4sIGNwID0gMC4wNDQpDQoNCiMgdHJlZSBiYXNlZCBvbiBnYXAgc2NvcmUgLS0gbGV0J3Mgbm90IHVzZSB0aGlzIGFzIHRyZWUzIGlzIG1vcmUgc3RhYmxlIGFuZCB3aWxsIG5vdCBjaGFuZ2UgYmFzZWQgb24gbmV3IDVXIGRhdGEgDQp0cmVlNCA8LSBwYXJyMCAlPiUNCiAgcnBhcnQoZ2FwX3Njb3JlIH4gZXN0YWRvICsgcGVyY2VudF91cmJhbmEgKyBkZW5zaWRhZF9wcGxfa20yICsNCiAgICAgICAgcmF6b25fZGVfZGVwZW5kZW5jaWFfZGVfbWVub3Jlc19kZV8xNV9hbm9zICsgcmF6b25fZGVfZGVwZW5kZW5jaWFfdG90YWwgKyAgDQogICAgICAgIHBlcmNlbnRfc2luX2FndWFfc2VndXJhICsgcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gKw0KICAgICAgICBwZXJjZW50X3Npbl9zZXJ2aWNpb19lbGVjdHJpY28gKyBwZXJjZW50X2FuYWxmYWJldG8gKyBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsIA0KICAgICAgICBwcm9tZWRpb19kZV9wZXJzb25hc19wb3Jfdml2aWVuZGEsIGRhdGEgPSAuLCBjcCA9IDAuMDQ1KQ0KDQojIGFkZGluZyB0cmVlMSBhbmQgdHJlZTMgcnVsZXMgdG8gdGhlIGRhdGFzZXQgDQpwYXJyMCA8LSBwYXJyMCAlPiUgDQogIG11dGF0ZShydWxlMSA9IHJvdy5uYW1lcyh0cmVlMSRmcmFtZSlbdHJlZTEkd2hlcmVdKSAlPiUNCiAgICAgIGxlZnRfam9pbihycGFydC5ydWxlcy50YWJsZSh0cmVlMSkgJT4lIA0KICAgICAgZmlsdGVyKExlYWYgPT0gVFJVRSkgJT4lIA0KICAgICAgcmVuYW1lKHJ1bGUxID0gUnVsZSkgJT4lIA0KICAgICAgZ3JvdXBfYnkocnVsZTEpICU+JSANCiAgICAgIHN1bW1hcmlzZShzdWJydWxlczEgPSBwYXN0ZShTdWJydWxlLCBjb2xsYXBzZSA9ICIsIikpKSAgJT4lIA0KICBtdXRhdGUocnVsZTMgPSByb3cubmFtZXModHJlZTMkZnJhbWUpW3RyZWUzJHdoZXJlXSkgJT4lDQogICAgICBsZWZ0X2pvaW4ocnBhcnQucnVsZXMudGFibGUodHJlZTMpICU+JSANCiAgICAgIGZpbHRlcihMZWFmID09IFRSVUUpICU+JSANCiAgICAgIHJlbmFtZShydWxlMyA9IFJ1bGUpICU+JSANCiAgICAgIGdyb3VwX2J5KHJ1bGUzKSAlPiUgDQogICAgICBzdW1tYXJpc2Uoc3VicnVsZXMzID0gcGFzdGUoU3VicnVsZSwgY29sbGFwc2UgPSAiLCIpKSkgJT4lIA0KICBtdXRhdGUocnVsZTQgPSByb3cubmFtZXModHJlZTQkZnJhbWUpW3RyZWU0JHdoZXJlXSkgJT4lDQogICAgICBsZWZ0X2pvaW4ocnBhcnQucnVsZXMudGFibGUodHJlZTQpICU+JSANCiAgICAgIGZpbHRlcihMZWFmID09IFRSVUUpICU+JSANCiAgICAgIHJlbmFtZShydWxlNCA9IFJ1bGUpICU+JSANCiAgICAgIGdyb3VwX2J5KHJ1bGU0KSAlPiUgDQogICAgICBzdW1tYXJpc2Uoc3VicnVsZXM0ID0gcGFzdGUoU3VicnVsZSwgY29sbGFwc2UgPSAiLCIpKSkNCg0KYGBgDQoNCg0KYGBge3J9DQpmYW5jeVJwYXJ0UGxvdCh0cmVlMywgZGlnaXRzID0gLTMsIHN1YiA9ICIiLCBwYWxldHRlcyA9ICJCbHVlcyIsIHR5cGUgPSAyKQ0KYGBgDQoNCg0KYGBge3J9DQpwbG90Y3AodHJlZTMpDQpgYGANCg0KIyMjIFByZWRpY3RpbmcgY292ZXJhZ2UgYXQgdGhlIHBhcnJpc2ggbGV2ZWwNCg0KPiBUaGUgc2ltcGxlIG1vZGVsIGJlbG93LCB0cmVlMiwgc2hvd3Mgd2hpY2ggdmFyaWFibGVzIGJlc3QgcHJlZGljdCB3aGV0aGVyIGEgcGFycmlzaCBoYXMgYmVlbiByZWFjaGVkIGJ5IGh1bWFuaXRhcmlhbiBhZ2VuY2llcyBvciBub3QgVGhpcyBpcyBub3QgdG8gaW1wbHkgdGhhdCB0aGlzIGFjdHVhbGx5IGRlcGljdHMgdGhlIGRlY2lzaW9uLW1ha2luZyBwcm9jZXNzIG9mIG91ciBwYXJ0bmVycywganVzdCB0aGF0IHRoZXNlIGFyZSB0aGUgZmFjdG9ycyB0b3dhcmRzIHdoaWNoIHdlLCBhcyBhIHJlcG9uc2UsIGFyZSBwcmVkaXNwb3NlZC4gDQoNCj4gVG8gdW5kZXJzdGFuZCB0aGUgcGxvdCBiZWxvdywgYWxsIHBhcnJpc2hlcyBoYXZlIGJlZW4gc3BsaXQgaW50byBmb3VyIGdyb3VwcyAodGhlIHRlcm1pbmFsIG5vZGVzIGF0IHRoZSBib3R0b20gbWFya2VkIFs0XSwgWzVdLCBbNl0gYW5kIFs3XSkgYmFzZWQgb24gdGhlIHBlcmNlbnRhZ2Ugb2YgcGFycmlzaGVzIGluIGVhY2ggbm9kZSB3aGVyZSBodW1hbml0YXJpYW4gYWdlbmNpZXMgYXJlIHByZXNlbnQuIEVhY2ggYnViYmxlIGhhcyB0aHJlZSBmaWd1cmVzIC0tIHRoZSBvbmUgb24gdGhlIHRvcCBzaG93cyB0aGUgcGVyY2VudGFnZSBvZiBwYXJpc2hlcyBpbiBlYWNoIGdyb3VwIHRoYXQgaGFzIGEgaHVtYW5pdGFyaWFuIHByZXNlbmNlOiBmb3IgaW5zdGFuY2UsIHRoZSByb290LCBhdCB0aGUgdG9wIGFuZCBtYXJrZWQgWzFdLCBzaG93cyB0aGF0IG9uIGF2ZXJhZ2UsIDAuNTQ3IG9yIDU0LjclIG9mIGFsbCBwYXJyaXNoZXMgaGF2ZSBodW1hbml0YXJpYW4gYWdlbmNpZXMgcHJlc2VudCBpbiB0aGVtLiBUaGUgbmV4dCBudW1iZXJzLCAibiA9IDExNjEiIHNob3cgdGhhdCAxMTYxIHBhcnJpc2hlcyBhcmUgaW4gdGhhdCBncm91cCBhbmQgdGhlIHBlcmNlbnRhZ2Ugb2YgcGFycmlzaGVzIGluIHRoYXQgZ3JvdXAuIA0KDQpgYGB7ciB0cmVlMi1ycGFydFBMT1R9DQoNCmZhbmN5UnBhcnRQbG90KHRyZWUyLCBkaWdpdHMgPSAtMywgc3ViID0gIiIsIHBhbGV0dGVzID0gIkJsdWVzIiwgdHlwZSA9IDIpDQpgYGANCg0KPiBXZSBjb21lIGF3YXkgd2l0aCBhIHNsaWdodGx5IHVuZmF2b3VyYWJsZSB2aWV3IG9mIG91ciBvcGVyYXRpb25hbCBmb290cHJpbnQuIFdlIGFyZSBtb3N0IHByZXNlbnQgaW4gcGFycmlzaGVzIHdoaWNoIGFyZSBib3RoIG1vcmUgdXJiYW4gYW5kIG1vcmUgZGVuc2UgLS0gYmVpbmcgcHJlc2VudCBpbiA4MyUgb2YgcGFycmlzaGVzIHdoaWNoIGFyZSBtb3JlIHRoYW4gNzklIHVyYmFuIGFuZCBoYXZlIG1vcmUgdGhhbiAxODcgcGVvcGxlIHBlciBrbTIgKHRoaXMgYXBwbGllcyB0byB0aGUgMzM3IHBhcnJpc2hlcyBpbiBub2RlIFs3XSkuIFBlcmhhcHMgaXQgaXMgdW5kZXJzdGFuZGFibGUgdGhhdCB0aGUgbW9zdCBoZWF2aWx5IHBvcHVsYXRlZCBwYXJyaXNoZXMgaGF2ZSBncmVhdGVyIG9yZ2FuaXNhdGlvbmFsIHByZXNlbmNlLiBCdXQgaXQgbXVzdCBiZSBtZW50aW9uZWQgdGhhdCBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIHVyYmFuIHBvcHVsYXRpb24gYXJlIGJvdGggbmVnYXRpdmVseSBjb3JyZWxhdGVkIHdpdGggcG92ZXJ0eSBpbmNpZGVuY2UuIEluIHRoZSBuZXh0IHNlY3Rpb24sIHdlIA0KDQo+IFRoZSBsYXJnZXN0IGRldGVybWluYW50cyBvZiB0aGUgKm51bWJlciogb2YgYmVuZWZpY2lhcmllcyByZWFjaGVkIHBlciBwYXJyaXNoIGFyZSBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIHBlcmNlbnRhZ2UgdXJiYW4sIGFzIGJlbmVmaWNpYXJ5IG51bWJlcnMgdGVuZCB0byBzY2FsZSBpbiBsaW5lIHdpdGggbGFyZ2VyIHBvcHVsYXRpb25zLiANCg0KIyMjIENoYXJhY3RlcmlzdGljcyBvZiB0aGUgcG9wdWxhdGlvbiBub3QgY292ZXJlZA0KDQo+IEluc3RlYWQgb2YgYSBzaW5ndWxhciBwcmlvcml0aXNhdGlvbiBzY29yZSwgd2hpY2ggaXMgdHlwaWNhbGx5IHRoZSB3ZWlnaHRlZCBhdmVyYWdlIG9mIHNldmVyYWwgc2Vjb25kYXJ5IGRhdGEgaW5kaWNhdG9ycywgYSB0cmVlIGlzIGJldHRlciBhdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZSB2YXJpb3VzIHByaW9yaXRpZXMgYW5kIGxpbWl0YXRpb25zIG9mIGVhY2ggcGFydG5lciAtLSBzb21lIG1pZ2h0IG5vdCBoYXZlIHRoZSBjYXBhY2l0eSB0byBleHBhbmQgb3V0c2lkZSBvZiB1cmJhbiBhcmVhcywgb3RoZXIgaGF2ZSBzcGVjaWZpYyBnZW9ncmFwaGljIGJpYXNlcyAtLSBhbmQgZGVjaXNpb24gdHJlZXMgYXJlIGEgdXNlZnVsIHRvb2wgdG8gbWFrZSB0aGUgYmVzdCB0YXJnZXR0aW5nIGRlY2lzaW9ucyBvbmUgY2FuIHdpdGhpbiBvbmUncyBjb25zdHJhaW50cy4gDQoNCj4gV2l0aCB0aGF0IGluIG1pbmQsIHRyZWUzIHdhcyBkZXZlbG9wZWQgdG8gYWlkIGZ1dHVyZSBwcmlvcml0aXNhdGlvbi4gVGhlIGluZGVwZW5kZW50IHZhcmlhYmxlIGl0IHN0cml2ZXMgdG8gcHJlZGljdCBpcyB0aGUgcG92ZXJ0eSBzY29yZSAodW5oaWRlIGNvZGUgaW4gc2VjdGlvbiB4eCB0byBzZWUgaXRzIHNwZWNpZmljIGNhbGN1bGF0aW9uKSwgd2hpY2gsIGFzIG1lbnRpb25lZCwgaXMganVzdCB0aGUgcmVzY2FsZWQgYXZlcmFnZSBvZiBudW1iZXIgb2YgcG9vciBwZXJzb25zIGFuZCBwb3ZlcnR5IGluY2lkZW5jZS4gVHJlZTMncyBwZXJmb3JtYW5jZSB3YXMgY29uc2lkZXJlZCBzdXBlcmlvciB0byB0cmVlMSBieSB0aGUgYW5hbHlzdCwgd2hpY2gganVzdCB1c2VkIHRoZSBhYnNvbHV0ZSBudW1iZXIgb2YgcG9vciBwZXJzb25zIGFzIGl0cyBpbmRlcGVuZGVudCB2YXJpYWJsZSwgZHVlIHRvIGl0cyBhYmlsaXR5IHRvIGNsZWFybHkgZGlzdGluZ3Vpc2ggaXRzIGdyb3VwcyBvZiBwYXJyaXNoZXMgDQoNCg0KYGBge3IgdHJlZTMtcnBhcnRQbG90fQ0KDQpmYW5jeVJwYXJ0UGxvdCh0cmVlNCwgZGlnaXRzID0gLTMsIHN1YiA9ICIiLCBwYWxldHRlcyA9ICJCbHVlcyIsIHR5cGUgPSAyKQ0KYGBgDQoNCmBgYHtyIHRyZWUzLXJ1bGVzfQ0KIyBmaWd1cmUgb3V0IHRoZSByaWdodCBvcmRlciBmb3IgdGhlIGxlYXZlcw0KIyBJJ20gbGlraW5nIHRyZWUzIG1vcmUgYW5kIG1vcmUNCiAgDQpwYXJyMCAlPiUgDQogIGdyb3VwX2J5KHJ1bGUzKSAlPiUgDQogIHN1bW1hcmlzZShwYXJyX25vX2JlbiA9IG5fZGlzdGluY3QocGNvZGUzW2JlbmVmaWNpYXJpb3MgPT0gMF0pLA0KICAgICAgICAgICAgYmVuZWZpY2lhcmlvcyA9IHN1bShiZW5lZmljaWFyaW9zKSwNCiAgICAgICAgICAgIGJlbl9wZXJfcGFyciA9IHN1bShiZW5lZmljaWFyaW9zKSAvIG4oKSwgDQogICAgICAgICAgICBub3RfY292ZXJlZCA9IHN1bShub3RfY292ZXJlZF9wb2JyZSksDQogICAgICAgICAgICBuY19wZXJfcGFyciA9IHN1bShub3RfY292ZXJlZF9wb2JyZSkgLyBuKCksDQogICAgICAgICAgICBhdmdfb3JnX2NvdW50ID0gbWVhbihvcmdfY291bnQpLA0KICAgICAgICAgICAgYXZnX3BvYmxhY2lvbiA9IG1lYW4ocG9ibGFjaW9uXzIwMTkpLA0KICAgICAgICAgICAgY292ZXJhZ2VfcGVyY2VudCA9IHN1bShiZW5lZmljaWFyaW9zKSAvIHN1bShwb2JsYWNpb25fMjAxOSksDQogICAgICAgICAgICBwZXJjZW50X3BvYnJlID0gc3VtKHBvYl9wb2JyZSkgLyBzdW0ocG9ibGFjaW9uXzIwMTkpLA0KICAgICAgICAgICAgcGVyY2VudF91cmJhbmEgPSBzdW0ocG9iX3VyYmFuYSkgLyBzdW0ocG9ibGFjaW9uXzIwMTkpLA0KICAgICAgICAgICAgZGVuc2lkYWRfcHBsX2ttMiA9IHN1bShwb2JsYWNpb25fMjAxOSkgLyBzdW0oYXJlYV9rbTIsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBwYXJyb3F1aWFzID0gbigpLA0KICAgICAgICAgICAgbXVuaWNpcGlvcyA9IG5fZGlzdGluY3QocGNvZGUyKSwNCiAgICAgICAgICAgIHBhcnJfcGVyX211biA9IG4oKSAvIG5fZGlzdGluY3QocGNvZGUyKSkgJT4lIA0KICBnYXRoZXIoa2V5ID0gdmFyX25hbWUsIHZhbHVlID0gdmFsdWUsIDI6bmNvbCguKSkgJT4lIA0KICBzcHJlYWRfKGtleSA9IG5hbWVzKC4pWzFdLCB2YWx1ZSA9ICd2YWx1ZScpICU+JSANCiAgYXJyYW5nZShmYWN0b3IodmFyX25hbWUsIGxldmVscyA9IGMoIm5vdF9jb3ZlcmVkIiwgIm5jX3Blcl9wYXJyIiwgImF2Z19wb2JsYWNpb24iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJlbmVmaWNpYXJpb3MiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmVuX3Blcl9wYXJyIiwgICJhdmdfb3JnX2NvdW50IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjb3ZlcmFnZV9wZXJjZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnRfcG9icmUiLCAicGVyY2VudF91cmJhbmEiLCAiZGVuc2lkYWRfcHBsX2ttMiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGFycm9xdWlhcyIsICJwYXJyX25vX2JlbiIsICJtdW5pY2lwaW9zIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwYXJyX3Blcl9tdW4iKSkpICU+JSAgDQogIA0KICBwYW5kZXIoYmlnLm1hcmsgPSAiLCIpDQoNCg0KIyA0IGlzIHBvcHVsYXRpb24gY2VudHJlcyB3aGljaCBhcmUgZWFzeSB0byByZWFjaCwgYnV0IHdpdGggb25seSAyNCUgb2YgdGhlIHBvcHVsYXRpb24gYmVpbmcgcG9vciwgDQojIGNhcmVmdWwgdGFyZ2V0dGluZyBhbmQgYmVuZWZpY2lhcnkgc2VsZWN0aW9uIGlzIHJlcXVpcmVkLiANCiMgNSBpcyBwcm9iYWJseSB0aGUgYmVzdCBvcHRpb24gZm9yIGV4cGFuc2lvbiAtLSBpdCBoYXMgdGhlIGhpZ2hlc3QgY29uY2VudHJhdGlvbiBvZiBwb29yIHBlcnNvbnMgbm90IGNvdmVyZWQgcGVyIHBhcnJpc2gsIGlzIHN1YnN0YW50aWFsbHkgcG9vcmVyIHRoYW4gQSAod2l0aCBhIDQwJSBwb3ZlcnR5IGluY2lkZW5jZSwgbWFraW5nIHRhcmdldHRpbmcgb2YgdnVsbmVyYWJsZSBwZXJzb25zIG11Y2ggZWFzaWVyKS4gQWRkaXRpb25hbGx5LCB0aGUgcGFycmlzaGVzIHdpdGhpbiB0aGlzIGdyb3VwIGFyZSBzdGlsbCB2ZXJ5IHVyYmFuaXNlZCAoOTElKQ0KIyBDIGlzIHByb2JhYmx5IHRoZSBiZXN0IG9wdGlvbiBmb3IgZXhwYW5zaW9uIC0tIGl0IGhhcyB0aGUgaGlnaGVzdCBjb25jZW50cmF0aW9uIG9mIHVuY29udmVyZWQgDQojIHBlcnNvbnMgcGVyIHBhcnJvcXVpYSBhbmQgbXVuaWNpcGlvLCBpcyBzdWJzdGFudGlhbGx5IHBvb3JlciB0aGFuIEEgKGF0IDQzJSBwb3ZlcnR5IGluY2lkZW5jZSkuIA0KIyBPcGVyYXRpb25hbCBleHBhbnNpb24gaXMgbW9yZSBsaWtlbHksIGR1ZSB0byB0aGUgaGlnaGVyIGNvbmNlbnRyYXRpb24gb2Ygb3JnYW5pc2F0aW9ucyBhbmQgDQojIGl0IGlzIGFsc28gZmFpcmx5IHVyYmFuLCBtZWFuaW5nIHRoYXQgdGhpcyB1bmNvdmVyZXZlZCBwb3B1bGF0aW9uIGlzIGZhaXJseSBlYXN5IHRvIHJlYWNoLiANCiMgYmV0dGVyIHRoYW4gQiBpbiBhbG1vc3QgZXZlcnkgd2F5IC0tIGhpZ2hlciBjb25jZW50cmF0aW9uIG9mIE5DLCBsZXNzIGFyZWEgdG8gY292ZXIgYW5kIA0KIyBpdCdzIGFscmVhZHkgZ290IGhpZ2hlciBvcGVyYXRpb25hbCBjb3ZlcmFnZSwgc28gdGhhdCBtYWtlczsgDQojIGluIGZhY3QsIEIgc2hvdWxkIGJlIHByaW9yaXRpc2VkIGhlcmUgLS0gaXQncyBlYXN5IHRvIA0KIyBpbiBtYW55IHdheXMsIEQgaXMgYmV0dGVyIHRoYW4gQyBhcyB3ZWxsDQojIEUgaXMganVzdCBhIGdpYW50IG9wZXJhdGlvbmFsIGNoYWxsZW5nZQ0KDQpgYGANCg0KPiBVbmhpZGUgZm9yIHRyZWUxIG5vdGVzIC0tIG1vdmUgdGhpcyB0byBhcHBlbmRpeA0KDQpgYGB7ciB0cmVlMS1ub3Rlc30NCg0KIyBWIGlzIGRlbnNlLCB1cmJhbiBhbmQgaGlnaGVzdCBvcGVyYXRpb25hbCBwcmVzZW5jZSwgc2hvcnRseSBmb2xsb3dlZCBieSBXDQojIFogaXMgYSBwcmlvcml0eSBmb3IgcmVhY2hpbmcgdGhlIG1vc3QgdnVsbmVyYWJsZSBhbmQgbWFyZ2luYWxpc2VkLCANCiMgYnV0IGl0IHRydWx5IGlzIHZlcnkgc3BhcnNlbHkgcG9wdWxhdGVkLiBUaGUgbnVtYmVyIG9mIHBlcnNvbnMgeW91IGNhbiByZWFjaCBpcyBsb3cgYW5kIA0KIyB0aGlzIGlzIHRoZSBtb3N0IG9wZXJhdGlvbmFsbHkgY2hhbGxlbmdpbmcNCiMgWSBpcyBtb3JlIHRoYW4gNTAlIHBvb3IsIGJ1dCBhbHNvIHNwYXJzZWx5IHBvcHVsYXRlZDsgYnV0IGl0IGhhcyBtb3JlIG5vdF9jb3ZlcmVkIHRoYW4gWCwgIHdpdGggZG91YmxlIHRoZSBudW1iZXIgb2Ygbm90X2NvdmVyZWQgcGVyIHBjb2RlMywgaXQgYWxzbyBoYXMgbGVzcyB0aGFuIGhhbGYgdGhlIA0KIyBtdW5pY2lwYWxpdGllcyAtLSBvcGVyYXRpb25hbGx5IG1vcmUgZmVhc2libGUgdG8gbW92ZSBpbnRvIHRoaXMgYXJlYQ0KIyBYIGlzIHNwcmVhZCBvdXQsIG51bWVyb3VzIGFuZCB5b3Ugc2hvdWxkIGV4cGFuZCB0aGVyZSBvbmx5IGlmIHlvdSBoYXZlIG9wZXJhdGlvbnMgaW4gYWRqYWNlbnQgYXJlYXMNCg0KcGFycjAgJT4lIA0KICBncm91cF9ieShydWxlMSkgJT4lIA0KICBzdW1tYXJpc2UocGFycl9ub19iZW4gPSBuX2Rpc3RpbmN0KHBjb2RlM1tiZW5lZmljaWFyaW9zID09IDBdKSwgDQogICAgICAgICAgICBiZW5lZmljaWFyaW9zID0gc3VtKGJlbmVmaWNpYXJpb3MpLA0KICAgICAgICAgICAgYmVuX3Blcl9wYXJyID0gc3VtKGJlbmVmaWNpYXJpb3MpIC8gbigpLCANCiAgICAgICAgICAgIG5vdF9jb3ZlcmVkID0gc3VtKG5vdF9jb3ZlcmVkX3BvYnJlKSwNCiAgICAgICAgICAgIG5jX3Blcl9wYXJyID0gc3VtKG5vdF9jb3ZlcmVkX3BvYnJlKSAvIG4oKSwNCiAgICAgICAgICAgIG5jX3Blcl9tdW4gPSBzdW0obm90X2NvdmVyZWRfcG9icmUpIC8gbl9kaXN0aW5jdChwY29kZTIpLCANCiAgICAgICAgICAgIGF2Z19vcmdfY291bnQgPSBtZWFuKG9yZ19jb3VudCksDQogICAgICAgICAgICBjb3ZlcmFnZV9wZXJjZW50ID0gc3VtKGJlbmVmaWNpYXJpb3MpIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSwNCiAgICAgICAgICAgIHBlcmNlbnRfcG9icmUgPSBzdW0ocG9iX3BvYnJlKSAvIHN1bShwb2JsYWNpb25fMjAxOSksDQogICAgICAgICAgICBwZXJjZW50X3VyYmFuYSA9IHN1bShwb2JfdXJiYW5hKSAvIHN1bShwb2JsYWNpb25fMjAxOSksDQogICAgICAgICAgICBkZW5zaWRhZF9wcGxfa20yID0gc3VtKHBvYmxhY2lvbl8yMDE5KSAvIHN1bShhcmVhX2ttMiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIHBhcnJvcXVpYXMgPSBuKCksDQogICAgICAgICAgICBtdW5pY2lwaW9zID0gbl9kaXN0aW5jdChwY29kZTIpLA0KICAgICAgICAgICAgcGFycl9wZXJfbXVuID0gbigpIC8gbl9kaXN0aW5jdChwY29kZTIpKSAlPiUgDQogIGdhdGhlcihrZXkgPSB2YXJfbmFtZSwgdmFsdWUgPSB2YWx1ZSwgMjpuY29sKC4pKSAlPiUgDQogIHNwcmVhZF8oa2V5ID0gbmFtZXMoLilbMV0sIHZhbHVlID0gJ3ZhbHVlJykgJT4lIA0KICBhcnJhbmdlKGZhY3Rvcih2YXJfbmFtZSwgbGV2ZWxzID0gYygibm90X2NvdmVyZWQiLCAibmNfcGVyX3BhcnIiLCAibmNfcGVyX211biIsICJiZW5lZmljaWFyaW9zIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJlbl9wZXJfcGFyciIsICAiYXZnX29yZ19jb3VudCIsICJjb3ZlcmFnZV9wZXJjZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnRfcG9icmUiLCAicGVyY2VudF91cmJhbmEiLCAiZGVuc2lkYWRfcHBsX2ttMiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGFycm9xdWlhcyIsICJwYXJyX25vX2JlbiIsICJtdW5pY2lwaW9zIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwYXJyX3Blcl9tdW4iKSkpICU+JSAgcGFuZGVyKGJpZy5tYXJrID0gIiwiKQ0KDQpgYGANCg0KDQpgYGB7cn0NCnBjb2RlM19zaGFwZSA8LSBzdF9yZWFkKCJDOi9Vc2Vycy9TZWFuIE5nL0RvY3VtZW50cy9SL2NvdmVyYWdlX2dhcHNfdmVuZXp1ZWxhL3Zlbl9hZG1ibmRhX2FkbTNfMjAxODA1MDIvdmVuX2FkbWJuZGFfYWRtM18yMDE4MDUwMi5zaHAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcXVpZXQgPSBUUlVFKSAlPiUgDQogIHJlbmFtZShwY29kZTEgPSBBRE0xX1BDT0RFLA0KICAgICAgICAgcGNvZGUyID0gQURNMl9QQ09ERSwNCiAgICAgICAgIHBjb2RlMyA9IEFETTNfUENPREUpDQoNCmBgYA0KDQo8YnI+PGJyPg0KDQoNCmBgYHtyfQ0KdW5pcXVlKHBhcnIkZXN0YWRvKQ0KYGBgDQoNCg0KYGBge3J9DQpwYXJyMCAlPiUgZmlsdGVyKHBlcmNlbnRfcG9icmUgPj0gMC42OTcpICU+JSANCiAgc3VtbWFyaXNlKHBhcnJvcXVpYXNfYmVuID0gbGVuZ3RoKHBjb2RlM1tiZW5lZmljaWFyaW9zID4gMF0pLA0KICAgICAgICAgICAgcGFycm9vcXVpYXMgPSBuKCkpDQpgYGANCg0KDQoNCg0KYGBge3J9DQojIGZvciBzaG93aW5nIHRoZSBvdXRwdXQgb2YgdGhlIHRyZWUgbmljZWx5DQpwcmludCh0cmVlMykNCg0KcHJpbnRjcCh0cmVlMykNCmBgYA0KPiBUcmVlMSBzcGxpdHMgcGFycm9xdWlhcyBieQ0KDQoNCg==